MySQL - 使用Join更新突然需要永远

时间:2016-05-31 09:00:30

标签: mysql performance join

我有一张主表 MainTable 。有大约4.5M行。 这是它的创建查询:

create table MainTable(
   status_day date DEFAULT NULL, 
   i_station_id int DEFAULT NULL, 
   i_TZ int DEFAULT NULL, 
   CID int DEFAULT NULL, 
   Calc1 double DEFAULT NULL, 
   Calc2 double DEFAULT NULL, 
   ...
   Calc80 double DEFAULT NULL, 
UNIQUE KEY uniqueindex (status_day, i_station_id, i_TZ, CID)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

我需要使用另一个 TEMP 表中的值更新多个字段。它有大约760K行,并且它创建语句:

create temporary table TEMP (
   status_day date DEFAULT NULL, 
   i_station_id int DEFAULT NULL, 
   i_TZ int DEFAULT NULL, 
   CID int DEFAULT NULL,, 
   Calc13 double DEFAULT NULL, 
   Calc14 double DEFAULT NULL, 
   Calc17 double DEFAULT NULL, 
   Calc24 double DEFAULT NULL, 
   Calc68 double DEFAULT NULL, 
   Calc70 double DEFAULT NULL, 
UNIQUE KEY indexxx (status_day, i_station_id, i_TZ, CID)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

由于某种原因,此更新查询:

需要约3个小时。那有意义吗?对我来说似乎太长了

update MainTable as A join TEMP as B on
        (A.status_day = B.status_day and 
        A.i_station_id = B.i_station_id and 
        A.i_TZ = B.i_TZ and 
        A.CID = B.CID) 
set 
   A.Calc13 = B.Calc13, 
   A.Calc14 = B.Calc14, 
   A.Calc17 = B.Calc17, 
   A.Calc24 = B.Calc24, 
   A.Calc68 = B.Calc68, 
   A.Calc70 = B.Calc70

这是

的结果
Explain select 
    * 
from MainTable as a join TEMP as b on
    (a.status_day = b.status_day and 
    a.i_station_id = b.i_station_id and 
    a.i_TZ = b.i_TZ and 
    a.CID = b.CID) 




ID     select_type   table    type    possible_keys  key          key_len rows  
1      SIMPLE        b        ALL     indexxx                             692967
1      SIMPLE        a        ref     uniqueindex    uniqueindex  23      1

有什么想法吗?

感谢? :)

更新:答案:服务器内存和CPU的增加立即解决了这个问题。

2 个答案:

答案 0 :(得分:0)

我不太清楚为什么查询花了3小时,这太荒谬了。也许您加入的列有问题,但您也可以进行如下查询:

UPDATE MainTable A, TEMP B
SET
     Calc13 = B.Calc13, 
     Calc14 = B.Calc14, 
     Calc17 = B.Calc17, 
     Calc24 = B.Calc24, 
     Calc68 = B.Calc68, 
     Calc70 = B.Calc70
WHERE
     A.status_day = B.status_day
     AND A.i_station_id = B.i_station_id
     AND A.i_TZ = B.i_TZ
     AND A.CID = B.CID

答案 1 :(得分:0)

3小时费用的一部分是建立一个巨大的"回滚"日志中。

我会围绕每次迭代更新1000行(或更少)进行构建。或者,更简单地说,在一个TEMP.status_day中更新一个UPDATE的所有行,然后转到下一个TEMP.status_day。可以使用存储过程或应用程序代码。

如果您这样做,请务必在COMMIT之后UPDATE。 (或者只使用autocommit=1。)

More on chunking