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