MySQL更新到表的末尾非常缓慢

时间:2017-08-14 14:50:41

标签: mysql performance innodb query-performance

我有一张桌子"数据"它拥有大约100,000,000条记录。 我已经添加了一个新列" batch_id" (整数)。

在应用程序层,我为100,000,000条记录中的每条记录批量更新10,000条记录(batch_id对于10k总是相同)。

我正在做这样的事情(应用程序层伪代码):

loop {
  $batch_id = $batch_id + 1;
  mysql.query("UPDATE data SET batch_id='$batch_id' WHERE batch_id IS NULL LIMIT 10000");
}

我在batch_id列上有一个索引。

一开始,这个更新语句花了大约30秒。我现在已经走到了桌子的中间位置,而且速度越来越慢。目前,同一声明大约需要10分钟(!)。它达到了不再可行的程度,因为以当前的速度更新整个表需要一个多月的时间。

我可以做些什么来加快速度,为什么MySQL会在表格结尾变慢? 主键上的索引可以帮助吗?

2 个答案:

答案 0 :(得分:2)

Is the primary key automatically indexed in MySQL?答案是肯定的

相反,batch_id的一个索引会有所帮助。

问题是没有索引引擎进行全表扫描。首先很容易找到10k的空值,但是当更新越来越多的记录时,引擎必须扫描更多才能找到这些空值。

但是应该更容易创建batch_id作为自动数字列

其他选项:创建一个新表,然后添加索引并替换旧表。

CREATE newTable as 
    SELECT IF(@newID := @newID + 1,
              @newID DIV 10000,
              @newID DIV 10000) as batch_id,
           <other fields>
    FROM YourTable         
    CROSS JOIN (SELECT @newID :=0 ) as v

Insert auto increment primary key to existing table

答案 1 :(得分:0)

你在桌子上有一个单调增加的id吗?并且“批次”的所有行都有“连续”ID?然后不要将batch_id添加到表中,而是创建另一个表Batches,每批一行:(batch_id(PK),id_start,id_end,start_time,end_time等)。

如果你坚持10K的确切块,那么甚至不要实现batch_id。而是在需要时从id DIV 10000计算它。

如果您想进一步讨论,请为现有表格提供SHOW CREATE TABLE,并解释您将对“批次”进行的操作。

要回答关于“接近结束的慢”的问题:必须在表格中越来越远地扫描以找到NULLs。你最好一次走过桌子,随便摆弄每个10K的大块。使用PRIMARY KEY执行此操作,无论它是什么。 (即使它不是AUTO_INCREMENT。)More Details