查询调优优化

时间:2015-07-07 13:29:51

标签: mysql sql subquery query-optimization query-tuning

以下是查询。此查询如何优化

SELECT  representative.rep_name                 AS RNAME, 
        SUM(areawise_temp.quantity*product.ptr) AS TOTPTR, 
        SUM(areawise_temp.quantity*product.pts) AS TOTPTS 
FROM    areawise_temp, 
        product, 
        representative 
WHERE   (areawise_temp.bill_date BETWEEN '2015/04/01' AND '2015/04/30') 
AND     areawise_temp.our_cust_id <> '' 
AND     areawise_temp.our_product_id <> '' 
AND     areawise_temp.Pincode IN 
(
    SELECT  pincode_list.pincode 
    FROM    pincode_list 
    WHERE   pincode_list.pin_id IN 
    (
        SELECT  rep_area.pin_id 
        FROM    rep_area 
        WHERE   rep_id IN 
        (
            SELECT  id 
            FROM    representative
        )
    ) 
    GROUP BY pincode_list.pincode
)  
AND areawise_temp.our_product_id = product.id

2 个答案:

答案 0 :(得分:0)

编码模式IN ( SELECT ... )的优化程度非常低。将其更改为JOIN

例如,最里面的部分可以是

SELECT ra.pin_id
    FROM rep_area AS ra
    JOIN representative AS r  ON r.id = ra.rep_id

还要确保您拥有必要的索引。让我们看SHOW CREATE TABLE来帮助你。对于上面的代码段,representative可能有PRIMARY KEY(id)

答案 1 :(得分:0)

在“优化”之前,请确保它返回正确的结果。对代表的交叉连接操作看起来很奇怪。没有GROUP BY,因此产品和数量的“总计”实际上乘以representative中的行数。 (这样做并没有效果,但结果却很奇怪 我们将质疑它。)

已经是2015年了。过去的时间抛弃了用于连接操作的旧式逗号语法。使用JOIN关键字。并将连接谓词从WHERE子句重定位到ON子句。

当我们省略连接谓词时,为了帮助未来的读者,我们希望包含CROSS关键字作为对有意省略连接谓词的指示。

另外,我会避免使用IN (subquery),并使用连接操作来获得相同的结果。

所以,首先,我会重新编写查询:

 SELECT r.rep_name            AS RNAME    -- not deterministic, no GROUP BY
      , SUM(t.quantity*p.ptr) AS TOTPTR
      , SUM(t.quantity*p.pts) AS TOTPTS 
   FROM areawise_temp t
   JOIN product p
     ON p.id = t.our_product_id
   JOIN ( SELECT l.pincode 
            FROM pincode_list l
            JOIN rep_area a
              ON a.pin_id = l.pin_id
            JOIN representative e
              ON e.id = a.rep_id
           GROUP BY l.pincode
        ) c
     ON c.pincode = t.pincode
  CROSS 
   JOIN representative r
  WHERE t.bill_date      BETWEEN '2015/04/01' AND '2015/04/30' 
    AND t.our_cust_id    <> ''
    AND t.our_product_id <> ''

这应该等同于原始查询,并返回相同的结果(可能具有不同的RNAME值,因为这是不确定的。)

不是belabor已经做出的一点,但是交叉加入representative看起来很奇怪。我强烈怀疑原始查询是而不是返回您实际想要返回的结果。

就性能而言,我们的下一个问题是our_cust_idour_product_id列的数据类型...如果这些是数字,则与空字符串的不等式比较是奇数。)数据类型bill_date的{​​{1}},如果那是DATE,那么我们真的希望文字有破折号分隔符,而不是斜线。 (我认为MySQL会很好地识别斜线,但我们更习惯于使用破折号查看日期文字,我们肯定知道它有用。)

基本上,我们想要了解我们强制MySQL执行的任何隐式数据类型转换,因为这些转换可能会影响是否可以使用索引。

“优化”这一步的下一步是使用EXPLAIN,查看访问计划,并评估我们期望使用的索引是否未使用,或者是否添加了合适的索引索引可能会提高绩效。

Optimizing queries using EXPLAIN https://dev.mysql.com/doc/refman/5.5/en/using-explain.html