2016-12-15 54 views
1

我正在mySQL服务器上运行更新查询/子查询,需要12分钟才能完成,我认为它不够优化。需要一种方法来优化慢SQL查询?

无论如何有人会想到优化它,所以它可以运行得更快吗?

在此先感谢。

UPDATE `TABLE_1` C 
INNER JOIN(

    SELECT Cust_No, 

    #current year sales 

    (SELECT SUM(`Sales`) 
    FROM `TABLE_2` 
    WHERE Year = 2016 
     AND Cust_No = p.Cust_No 
    ) as CY_TOTAL_SALES, 

    # Get previou year sales 

     (SELECT SUM(`Sales`) 
    FROM `TABLE_2` 
    WHERE Year = 2015 
     AND Cust_No = p.Cust_No 
    ) as PY_TOTAL_SALES 

    FROM `TABLE_2` p 
    WHERE Year >= 2015 
     AND Year <= 2016 

) AS A ON C.`customer_number` = A.Cust_No 
    SET C.CY_TOTAL_SALES = A.CY_TOTAL_SALES, 
     C.PY_TOTAL_SALES = A.PY_TOTAL_SALES; 

TABLE_1包含28000条记录(CUSTOMER_NUMBER领域是独一无二的,编入索引建)

TABLE_2包含25万条记录(CUST_NO不是唯一的,但编入索引建)

它就是更新TABLE_1通过加入Table_2并使用子查询总结TABLE_2中两年的总销售额值,然后将值更新回TABLE_1 WHERE TABLE_1定制员编号与TABLE_2 Cust_no匹配。

+2

用'EXPLAIN'运行查询并发布输出。这将显示哪部分查询很昂贵。 –

回答

3

我可以想到一些可能的解决方案。

方法一

只做一个子查询,没有做任何相关子查询,并和有条件基于一年。

UPDATE TABLE_1 C 
INNER JOIN (
    SELECT Cust_No, 
    SUM(IF(Year=2015, Sales, 0)) AS PY_TOTAL_SALES, 
    SUM(IF(Year=2016, Sales, 0)) AS CY_TOTAL_SALES 
    FROM TABLE_2 
    WHERE Year IN (2015, 2016) 
    GROUP BY Cust_No 
) AS S ON C.customer_number = S.Cust_No 
SET C.PY_TOTAL_SALES = S.PY_TOTAL_SALES, 
    C.CY_TOTAL_SALES = S.CY_TOTAL_SALES; 

方法二

都做不子查询。

首先,零出总销量为所有客户:

UPDATE TABLE_1 C 
SET C.CY_TOTAL_SALES = 0, 
    C.PY_TOTAL_SALES = 0; 

然后做一个连接,而无需使用任何子查询或SUM()电话,一次添加每个销售数字一到总销售额为客户。

UPDATE TABLE_1 AS C 
INNER JOIN TABLE_2 AS S ON C.customer_number = S.Cust_No 
SET C.CY_TOTAL_SALES = C.CY_TOTAL_SALES + IF(S.Year=2016, S.Sales, 0) 
    C.PY_TOTAL_SALES = C.PY_TOTAL_SALES + IF(S.Year=2015, S.Sales, 0) 
WHERE S.Year IN (2015, 2016); 

对于这两种方案,你会想要在列(CUST_NO,年销售)在TABLE_2的指标。


在此期间,我可以解释一下为什么您原来的查询太慢了。你的子查询读取TABLE_2,你说它有250,000行(我假设所有行都在2015-2016),并且每行都计算相应客户的总销售额。这意味着它会为每个客户多次计算相同的金额。

您正在运行500,000个相关的子查询!这实际上是一个奇迹,它只需要12分钟。

因为这样做,它将整个结果保存在250,000行临时表中,因为子查询。

然后它将临时表加入TABLE_1,并为每个客户设置CY_TOTAL_SALES和PY_TOTAL_SALES。你不知道,但它为每个客户设置了多次相同的总数。

+0

谢谢,并会尝试你的解决方案,看看。 –

+1

嗨比尔,感谢您的详细解释和方法,一个工作最好只需要1.2秒。非常感谢你的帮助。 –

0

由于新的用户信誉,无法添加注释。

没有看到表结构和当前索引将很难分辨如何优化您当前的查询。 请编辑您的问题以包含表格结构(show create table)。

+0

感谢您的回复,为什么表格结构有所不同? TABLE_1有98个字段,Customer_Number被设置为varchar(20),TABLE_2有25个字段,字段cust_no也被设置为varchar(20)。这两个表在不同领域有大约10个不同的索引。 –

+0

我看到你们得到了一个“更好”的变体 - 我同意Bill对这个问题的看法。我想我更像是一个视觉化的人,并且想在我给出答案之前在我的最后玩这个。 – Raul

+0

此外,该查询的解释可能会告诉你查询的最慢部分在哪里。这是调试查询性能时需要使用的最有用的信息 - 始终也包含这些信息! – Raul