为什么这个SQL查询需要永远?

时间:2015-01-30 07:09:29

标签: mysql sql performance

我尝试运行此查询,但它挂起了mysql服务器。它击中了大约5​​00万条记录。即使是解释查询也没有及时返回任何内容。

Explain SELECT COUNT(*)   FROM
(SELECT COUNT(DISTINCT Oms_Cart_Id )  Carts,Buyer_Id  
 FROM  Reporting.Order_Details  WHERE Buyer_Id  IN
    ( SELECT Buyer_Id
    FROM Reporting.Order_Details 
    WHERE Payment_Receive_Date>='2015-01-18 00:00:00' AND  
    Payment_Receive_Date<='2015-01-24 23:59:59'
    GROUP BY  Buyer_Id )  
 AND Payment_Receive_Date>='2014-09-01 00:00:00'   
 AND  Payment_Receive_Date<='2015-01-24 23:59:59'
 GROUP BY 2) X
 WHERE Carts>1
 LIMIT 0, 1000 ;

2 个答案:

答案 0 :(得分:0)

您向我们展示的查询应该是&#34;点击&#34;除非reporting.order_details是联合表,否则大约4行。假设不是这种情况,或者您的查询被其他东西阻止,或者您的服务器出现了问题。 Mysqladmin进程列表会告诉你前者是否是这种情况。您的系统日志应显示磁盘的任何问题。如果不是这种情况,那么您的数据文件可能已损坏。

答案 1 :(得分:0)

(是的,大脑受伤)

  1. 摆脱无用的LIMIT,只返回一行。

  2. 将外围的WHERE变成内在的HAVING(没有充分理由)

  3. 将IN(SELECT ...)转换为JOIN。我开始做一个自我加入,但是GROUP BY说或许子查询只提供了几个Buyer_Ids。所以,我做了JOIN(SELECT ...)

  4. 结果:

    SELECT  COUNT(*)
        FROM  
          ( SELECT  COUNT(DISTINCT a.Oms_Cart_Id ) Carts,
                    a.Buyer_Id
                FROM  Reporting.Order_Details a
                JOIN  
                  ( SELECT  Buyer_Id
                        FROM  Reporting.Order_Details
                        WHERE  Payment_Receive_Date>='2015-01-18 00:00:00'
                          AND  Payment_Receive_Date<='2015-01-24 23:59:59'
                        GROUP BY  Buyer_Id
                  ) AS b USING(Buyer_Id)
                WHERE  a.Payment_Receive_Date>='2014-09-01 00:00:00'
                  AND  a.Payment_Receive_Date<='2015-01-24 23:59:59'
                GROUP BY  2
                HAVING  Carts > 1 
          ) X ;
    

    Order_Details将受益于这两个

    INDEX(Buyer_Id) - 对于JOIN。 (如果您已经使用Buyer_Id开始 索引,请不要添加此索引。)

    INDEX(Payment_Receive_Date, Buyer_Id) - 用于子查询

    如果你真的只做一个COUNT(*):

    ,也许可以进一步简化
    SELECT  COUNT(DISTINCT Buyer_Id)
        FROM  Reporting.Order_Details a
        JOIN  
          ( SELECT  Buyer_Id
                FROM  Reporting.Order_Details
                WHERE  Payment_Receive_Date>='2015-01-18 00:00:00'
                  AND  Payment_Receive_Date<='2015-01-24 23:59:59'
                GROUP BY  Buyer_Id
          ) AS b USING(Buyer_Id)
        WHERE  Payment_Receive_Date>='2014-09-01 00:00:00'
          AND  Payment_Receive_Date<='2015-01-24 23:59:59'
        GROUP BY  2
        HAVING  COUNT(DISTINCT a.Oms_Cart_Id) > 1