Mysql 需要一种优化慢速SQL查询的方法吗?

Mysql 需要一种优化慢速SQL查询的方法吗?,mysql,sql,subquery,Mysql,Sql,Subquery,我正在mySQL服务器上运行一个更新查询/子查询,需要12分钟才能完成,我认为这还不够优化 有没有人能想办法优化它,让它运行得更快 提前谢谢 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

我正在mySQL服务器上运行一个更新查询/子查询,需要12分钟才能完成,我认为这还不够优化

有没有人能想办法优化它,让它运行得更快

提前谢谢

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;
表_1包含28000条记录客户_编号字段唯一且已建立索引

表2包含250000条记录。客户编号不是唯一的,但已建立索引


它所做的是通过连接表2来更新表1,并使用子查询来汇总表2中两年的总销售额,然后将值更新回表1,其中表1的客户编号与表2的客户编号匹配。

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

如果看不到表结构和当前索引,就很难知道如何优化当前查询。
请编辑您的问题以包含“显示创建表”的表结构。

由于新用户的声誉,无法添加评论

如果看不到表结构和当前索引,就很难知道如何优化当前查询。
请编辑您的问题,使其包含“显示创建表格”的表格结构。

我可以想出几个可能的解决方案

方法一

只执行一个子查询,不执行任何相关子查询,并根据年份有条件地求和

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;
然后在不使用任何子查询或求和调用的情况下进行联接,并将每个销售数字一次添加到客户的总销售额中

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);
对于这两种解决方案,您都希望在表2中的Cust_No、Year、Sales列上有一个索引

同时,我可以解释一下为什么您最初的查询如此缓慢。您的子查询读取表_2,您说它有250000行,我假设所有的行都是在2015-2016年,每行它计算相应客户的总销售额。这意味着它会为每个客户多次计算相同的金额

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

在执行此操作时,由于子查询,它将整个结果保存在一个250000行的临时表中


然后,它将临时表连接到表1,并为每个客户设置CY_TOTAL_SALES和PY_TOTAL_SALES。您不知道,但它为每个客户设置了多次相同的总数。

我可以想出几种可能的解决方案

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);
方法一

只执行一个子查询,不执行任何相关子查询,并根据年份有条件地求和

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;
然后在不使用任何子查询或求和调用的情况下进行联接,并将每个销售数字一次添加到客户的总销售额中

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);
对于这两种解决方案,您都希望在表2中的Cust_No、Year、Sales列上有一个索引

同时,我可以解释一下为什么您最初的查询如此缓慢。您的子查询读取表_2,您说它有250000行,我假设所有的行都是在2015-2016年,每行它计算相应客户的总销售额。这意味着它会为每个客户多次计算相同的金额

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

在执行此操作时,由于子查询,它将整个结果保存在一个250000行的临时表中


然后,它将临时表连接到表1,并为每个客户设置CY_TOTAL_SALES和PY_TOTAL_SALES。您不知道,但它为每个客户设置了多次相同的总数。

感谢您的回答,为什么表结构会有所不同?表1有98个字段,客户编号设置为varchar20,表2有25个字段,客户编号设置为varchar20。这两个表在不同的字段上都有大约10个不同的索引。我看到你们得到了一个更好的变体——我同意比尔的说法。我想我更喜欢视觉,我想在给出答案之前先玩一下这个。另外,对这个查询的解释可以告诉你查询最慢的部分在哪里。这是调试查询性能时需要使用的最有帮助的信息,请始终包括这些信息!感谢您的回复,为什么表结构会有所不同?表1有98个字段,客户编号设置为varchar20,表2有25个字段,客户编号设置为varchar20。这两个表在不同的字段上都有大约10个不同的索引。我看到你们得到了一个更好的变体——我同意比尔的说法。我想我更喜欢视觉,我想在给出答案之前先玩一下这个。另外,对这个查询的解释可以告诉你查询最慢的部分在哪里。这是你需要的最有用的信息
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);

调试查询性能时使用se-始终也包括该选项!使用EXPLAIN运行查询并发布输出。这将显示查询的哪些部分比较昂贵。使用EXPLAIN运行查询并发布输出。这将显示查询的哪些部分是昂贵的。谢谢,我们将试用您的解决方案并查看。嗨,比尔,谢谢您的详细解释,并且“一个是最好的”方法只需1.2秒。非常感谢您的帮助。谢谢,我们将试用您的解决方案并查看。嗨,比尔,谢谢您的详细解释,方法一最有效只需1.2秒。非常感谢你的帮助。