MariaDB:更新数十亿条记录的最佳方式

时间:2014-10-23 20:16:50

标签: mysql database timestamp mariadb

我正在寻找一种更新一个表中数十亿条记录的最佳方法(表3中的示例)。每个条目都与时间戳相关联,该时间戳的大小为毫秒级。在此示例中,表3已过期,表1和表2是最新的,其中包含各自数据的实际条目。我没有将表1和表2连接到表3的任何内容。如果需要,请告诉我,因为我不是数据库专家。

表1有4列:

Timestamp T_0 PRIMARY KEY (ex: '2014-07-04 16:17:16.800000')
X1_T1 VARCHAR
X2_T1 VARCHAR
X3_T1 VARCHAR

表2有4列:

Timestamp T_0 PRIMARY KEY (ex: '2014-07-04 16:17:16.800000')
X1_T2 VARCHAR
X2_T2 VARCHAR
X3_T3 VARCHAR

表3有7列:

Timestamp T_0 PRIMARY KEY (ex: '2014-07-04 16:17:16.800000')
X1_T1 VARCHAR
X2_T1 VARCHAR
X3_T1 VARCHAR
X1_T2 VARCHAR
X2_T2 VARCHAR
X3_T3 VARCHAR

我使用循环时间戳并使用命令更新每一行的过程成功更新了表3:

SET tmp_T_0=(SELECT '2014-01-05 17:00:00.000000'); // set to the start of the table's timestamp
label1: LOOP
  UPDATE TABLE3 SET
      X1_T1=(select X1_T1 FROM TABLE1 where T_0 = tmp_T_0),
      X2_T1=(select X2_T1 FROM TABLE1 where T_0 = tmp_T_0),
      X3_T1=(select X3_T1 FROM TABLE1 where T_0 = tmp_T_0),
      X1_T2=(select X1_T2 FROM TABLE2 where T_0 = tmp_T_0),
      X2_T2=(select X2_T2 FROM TABLE2 where T_0 = tmp_T_0),
      X3_T2=(select X3_T2 FROM TABLE2 where T_0 = tmp_T_0)
 WHERE T_0 = tmp_T_0;  

 SET tmp_T_0=(SELECT TIMESTAMP(tmp_T_0,'00:00:00.001')); //ADD one millisecond and continue

 SET LoopInt=(SELECT(LoopInt + 1));
 IF LoopInt < LoopEnd THEN
   ITERATE label1;
 END IF;
 LEAVE label1;
END LOOP label1;

对于100,000个条目,上述方法大约需要53秒。这是不可接受的,因为完成剩下的参赛作品需要大约100天。

应该注意的是,表3具有来自表1和/或2的每个时间戳条目的数据不是必须的(即,表3中的时间戳可以包含X1_T1 X2_T1的数据和X3_T1而其他值X1_T2 X2_T2和X3_T2为NULL)。

任何建议都会有所帮助。 谢谢

1 个答案:

答案 0 :(得分:0)

尝试此查询从TABLE1到TABLE3提取一小时的信息怎么样?

UPDATE TABLE3 AS t3
  JOIN TABLE1 AS t1 ON t3.T_0 = t1.T_0
   SET t3.X1_T1 = IFNULL(t1.X1_T1,t3.X1_T1),
       t3.X2_T1 = IFNULL(t1.X2_T1,t3.X2_T1),
       t3.X3_T1 = IFNULL(t1.X3_T1,t3.X3_T1)
 WHERE t3.T_0 >= '2014-01-05' + INTERVAL 0 HOUR
   AND t3.T_0 <  '2014-01-05' + INTERVAL 1 HOUR

发生了什么?首先,WHERE子句将查询的范围限制为一小时。这很方便,因为你可以测试一些东西。此外,您还希望逐个小时循环播放此作业,以免您的查询运行时间过长。如果您使用InnoDB或Aria作为存储引擎,如果您不限制查询范围,那么您也会破坏事务回滚空间。

您可以多次运行此查询,每次更改HOUR间隔,就像这样。

 WHERE t3.T_0 >= '2014-01-05' + INTERVAL 1 HOUR
   AND t3.T_0 <  '2014-01-05' + INTERVAL 2 HOUR

您正在将TABLE1加入TABLE3。这是有效的,因为您说TABLE3包含每个可能的时间戳,而TABLE1不包含。我编写此查询的方式,它不会触及TABLE3中没有TABLE1中相应行的行。我认为这就是你想要的。

最后,当有非NULL TABLE1数据时,IFNULL()函数只安排改变TABLE3数据。

看,如果你的TABLE1数据稀疏(也就是说,它在表中有很多随机分散的有效值,大多数是NULL)你可能想要使用这样的三个查询,所以你实际上并不是这样除非您有新数据,否则更改TABLE3中的行。更改行中的值相对昂贵。

UPDATE TABLE3 AS t3
  JOIN TABLE1 AS t1 ON t3.T_0 = t1.T_0
   SET t3.X1_T1 = t1.X1_T1
 WHERE t3.T_0 >= '2014-01-05' + INTERVAL 0 HOUR
   AND t3.T_0 <  '2014-01-05' + INTERVAL 1 HOUR
   AND t1.X1_T1 IS NOT NULL

UPDATE TABLE3 AS t3
  JOIN TABLE1 AS t1 ON t3.T_0 = t1.T_0
   SET t3.X2_T1 = t1.X2_T1
 WHERE t3.T_0 >= '2014-01-05' + INTERVAL 0 HOUR
   AND t3.T_0 <  '2014-01-05' + INTERVAL 1 HOUR
   AND t1.X2_T1 IS NOT NULL

UPDATE TABLE3 AS t3
  JOIN TABLE1 AS t1 ON t3.T_0 = t1.T_0
   SET t3.X3_T1 = t1.X3_T1
 WHERE t3.T_0 >= '2014-01-05' + INTERVAL 0 HOUR
   AND t3.T_0 <  '2014-01-05' + INTERVAL 1 HOUR
   AND t1.X3_T1 IS NOT NULL

您需要为TABLE2数据重复所有这些。

您可能希望在单个查询中运行此全部内容。别这么做!这是您需要能够一次完成一小时并在需要时重新启动的工作。我建议一次一个小时,但这是3.6个megarows。你可能想要一次做更小的块,比如6分钟(360千里)。

如果我是你,我肯定会在几天的时间内调试整个交易。&#39;值得你的TABLE3。