OR子句减慢SQL查询

史蒂夫

对于以下查询,我需要您的帮助,该查询需要2分钟以上的时间才能返回结果:

SELECT 
    p.weight, 
    o.login,
    o.date, 
    o.s_address, 
    o.s_city, 
    o.s_county, 
    o.s_state, 
    o.s_country, 
    o.s_zipcode, 
    o.phone, 
    c.categoryid, 
    c.category, 
    o.orderid, 
    p.product product_name, 
    p.productcode sku, 
    d.amount, 
    v.value emplacement, 
    ( SELECT ev.value FROM xcart_extra_field_values ev LEFT JOIN xcart_extra_fields ef ON ef.fieldid=ev.fieldid WHERE ev.productid = d.productid AND ef.field = 'a_type' LIMIT 1 ) type, 
    o.customer_notes, 
    o.membership, 
    o.s_firstname, 
    o.s_lastname, 
    o.phone, 
    d.price, 
    o.email 
FROM `xcart_orders` o 
LEFT JOIN `xcart_shipping` s ON s.shippingid=o.shippingid 
LEFT JOIN `xcart_order_details` d ON d.orderid=o.orderid 
LEFT JOIN `xcart_products` p ON p.productid=d.productid 
LEFT JOIN `xcart_products_categories` pc ON pc.productid=p.productid 
LEFT JOIN `xcart_categories` c ON c.categoryid=pc.categoryid 
LEFT JOIN `xcart_extra_field_values` v ON v.productid=p.productid 
LEFT JOIN `xcart_extra_fields` f ON f.fieldid=v.fieldid 
WHERE o.shippingid IN ( SELECT DISTINCT shippingid FROM `xcart_rafale_shipping` WHERE rafale='1' ) 
AND ( 
    SELECT COUNT(*) 
    FROM `xcart_order_details` d2 
    LEFT JOIN `xcart_products_categories` pc2 ON pc2.productid=d2.productid 
    WHERE d2.orderid=o.orderid 
    AND pc2.categoryid NOT IN ( SELECT DISTINCT ac2.categoryid FROM `xcart_rafale_aggregation_categories` ac2 WHERE ac2.aggregationid='12' ) 
) = 0 
AND ( 
    ( o.date BETWEEN '1386802800' AND '1386889199' ) 
    OR (o.orderid IN ('44', '55', '66')) 
) 
AND o.orderid NOT IN ('11', '22', '33', '123', '458') 
AND o.paid = 'Y' 
AND o.status <> 'F' 
AND o.status <> 'Q' 
AND o.status <> 'I' 
AND f.field = 'emplacement' 
AND pc.main = 'Y' 
ORDER BY v.value ASC, p.productcode ASC 
LIMIT 100

问题可能来自以下子句

AND ( 
    ( o.date BETWEEN '1386802800' AND '1386889199' ) 
    OR (o.orderid IN ('44', '55', '66')) 
)

因为当我删除查询时查询执行得更快 OR (o.orderid IN ('44', '55', '66'))

在o.date和o.orderid列上都有索引

我使用了下面的查询,该查询的灵感来自@ Clockwork-Muse的回复:

SELECT 
    p.weight, 
    o.login,
    o.date, 
    o.s_address, 
    o.s_city, 
    o.s_county, 
    o.s_state, 
    o.s_country, 
    o.s_zipcode, 
    o.phone, 
    c.categoryid, 
    c.category, 
    o.orderid, 
    p.product product_name, 
    p.productcode sku, 
    d.amount, 
    v.value emplacement, 
    ( SELECT ev.value FROM xcart_extra_field_values ev LEFT JOIN xcart_extra_fields ef ON ef.fieldid=ev.fieldid WHERE ev.productid = d.productid AND ef.field = 'a_type' LIMIT 1 ) type, 
    o.customer_notes, 
    o.membership, 
    o.s_firstname, 
    o.s_lastname, 
    o.phone, 
    d.price, 
    o.email
FROM `xcart_order_details` d
INNER JOIN (SELECT *
            FROM `xcart_orders`
            WHERE (
                orderid IN ('44', '55', '66') 
                OR (`date` >= '1386802800' AND `date` <= '1386889199')
            )
            ) o
        ON o.orderid = d.orderid
INNER JOIN (SELECT DISTINCT shippingid
            FROM `xcart_rafale_shipping`
            WHERE rafale = '1') rf
        ON rf.shippingid = o.shippingid
INNER JOIN `xcart_shipping` s ON s.shippingid=o.shippingid  
INNER JOIN `xcart_products` p ON p.productid=d.productid
INNER JOIN (SELECT *
            FROM `xcart_products_categories`
            WHERE main = 'Y') pc
        ON pc.productid=p.productid
LEFT JOIN `xcart_categories` c ON c.categoryid=pc.categoryid
LEFT JOIN `xcart_extra_field_values` v ON v.productid=p.productid  
LEFT JOIN `xcart_extra_fields` f ON f.fieldid=v.fieldid
WHERE NOT EXISTS ( 
    SELECT d2.orderid 
    FROM `xcart_order_details` d2 
    LEFT JOIN `xcart_products_categories` pc2 ON pc2.productid=d2.productid 
    WHERE d2.orderid=o.orderid 
    AND pc2.categoryid NOT IN ( SELECT DISTINCT ac2.categoryid FROM `xcart_rafale_aggregation_categories` ac2 WHERE ac2.aggregationid='12' ) 
) 
AND o.orderid NOT IN ('11', '22', '33', '123', '458') 
AND o.paid = 'Y'
AND o.status NOT IN ('F', 'Q', 'I')
AND f.field = 'emplacement'
发条缪斯

除了查询所遇到的其他任何问题或可能需要的索引外,它所做的工作还比需要做的要多。这是经过稍微调整的版本,可能会运行得更快:

SELECT 
    p.weight, 
    o.login,
    o.date, 
    o.s_address, 
    o.s_city, 
    o.s_county, 
    o.s_state, 
    o.s_country, 
    o.s_zipcode, 
    o.phone, 
    c.categoryid, 
    c.category, 
    o.orderid, 
    p.product product_name, 
    p.productcode sku, 
    d.amount, 
    v.value emplacement, 
    (SELECT ev.value 
     FROM xcart_extra_field_values ev 
     INNER JOIN xcart_extra_fields ef 
             ON ef.fieldid = ev.fieldid
                AND ef.field = 'a_type'  
     WHERE ev.productid = d.productid) type, 
    o.customer_notes, 
    o.membership, 
    o.s_firstname, 
    o.s_lastname, 
    o.phone, 
    d.price, 
    o.email 
FROM `xcart_orders` o
INNER JOIN (SELECT DISTINCT shippingid
            FROM `xcart_rafale_shipping`
            WHERE rafale = '1') rf
        ON rf.shippingid = o.shippingid
LEFT JOIN `xcart_shipping` s 
       ON s.shippingid = o.shippingid 
LEFT JOIN `xcart_order_details` d 
       ON d.orderid = o.orderid 
LEFT JOIN `xcart_products` p 
       ON p.productid = d.productid 
LEFT JOIN `xcart_products_categories` pc 
       ON pc.productid = p.productid
          AND pc.main = 'Y'
LEFT JOIN `xcart_categories` c 
       ON c.categoryid = pc.categoryid 
LEFT JOIN `xcart_extra_field_values` v 
       ON v.productid = p.productid 
LEFT JOIN `xcart_extra_fields` f 
       ON f.fieldid = v.fieldid
          AND f.field = 'emplacement'  
WHERE NOT EXISTS (SELECT *
                  FROM `xcart_products_categories` pc2
                  LEFT JOIN `xcart_rafale_aggregation_categories` ac2
                         ON ac2.categoryid = pc2.categoryid
                            AND ac2.aggregationid = '12'
                  WHERE pc2.productid = d.productid
                        AND ac2.categoryid IS NULL)
AND ((o.date >= '1386802800' AND o.date <'1386889200') 
     OR o.orderid IN ('44', '55', '66')) 
AND o.orderid NOT IN ('11', '22', '33', '123', '458') 
AND o.paid = 'Y' 
AND o.status NOT IN ('F', 'Q', 'I')        
ORDER BY v.value ASC, p.productcode ASC 
LIMIT 100

其他几件事-

  1. LEFT JOINWHERE子句中s条件-实际上这会将它们变成INNER JOINs。我已经将相关条件移到了联接中,这很可能会改变您的结果。如果您想要一个实际的INNER JOIN,只需更改/删除该词即可。这就是为什么在可能的情况下最好将所有条件都放入一个联接中的原因。
  2. 日期/时间/时间戳(即使未按该类型存储)也是一种“度量”-从逻辑上讲,所有度量在记录中都有一定的不准确性;为了反映这一点,请使用“下限包含,上限排除”(a >= x < b,需要翻转为负值)进行比较。为了保持一致性,我也建议将其用于整数计数。
  3. 没有ORDER BY子句,对LIMIT(或类似语句)的任何使用都将返回本质上不可控制的结果。如果只需要一个值,则必须执行以下操作之一-1)使用聚合(MAX(),等等),2)将查询/结构写到数据库中,以便仅一个值满足条件; 3)提供一个相关的值ORDER BY。使用“选择位置x”类型的构造。否则,查询将在最不期望的时候返回意外结果(也不会发出警告)。在这种情况下,我发现EAV表中不止有一个值实例(基本上是情况#2),这是极不可能的。
  4. 您的原始查询包含一个比较模糊的双负号(SELECT COUNT(*) ... = 0))。不幸的是,在不了解数据/表模式的本质的情况下,我无法真正消除双重否定(尽管我可以使其更加明显。为了将来的维护者,请尽可能避免双重否定。在这种情况下,这是因为您(也许过度)使用了LEFT-joins-您确定不需要信息吗?

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

ORDER BY子句会减慢查询速度吗?

来自分类Dev

SQL Server存储的proc减慢查询速度

来自分类Dev

SQL Server存储的proc减慢查询速度

来自分类Dev

IN()子句中的SQL查询

来自分类Dev

sql where子句查询

来自分类Dev

带OR子句的SQL查询

来自分类Dev

SQL 查询子句的顺序

来自分类Dev

SQL In子句语法查询错误

来自分类Dev

SQL查询多个where子句

来自分类Dev

SQL查询使用组子句

来自分类Dev

在SQL Server中查询WITH子句

来自分类Dev

SQL查询中的WHERE子句

来自分类Dev

使用 WHERE IN 子句的 SQL 查询

来自分类Dev

使用 With 子句的相关 SQL 查询

来自分类Dev

为什么DATEADD会减慢SQL查询的速度?

来自分类Dev

为什么DATEADD会减慢SQL查询的速度?

来自分类Dev

排序减慢查询速度

来自分类Dev

SQL查询:On子句和where子句的条件差异

来自分类Dev

带有LINQ查询子查询的not in子句的SQL查询

来自分类Dev

SQL查询中不包含where子句

来自分类Dev

SQL查询where子句以进行报告

来自分类Dev

SQL查询中的动态WHERE子句

来自分类Dev

SQL查询:在WHERE子句中使用AND / OR

来自分类Dev

WHERE子句中的HIVE SQL子查询

来自分类Dev

sql查询-如果WHERE子句中存在

来自分类Dev

SQL查询的WHERE子句中的CASE语句

来自分类Dev

SQL Group By子句如何划分查询结果

来自分类Dev

使用参数为IN子句的SQL Server查询

来自分类Dev

SQL查询不检查之后和子句