我有一张桌子"数据"它拥有大约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会在表格结尾变慢? 主键上的索引可以帮助吗?
答案 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
答案 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。