2017-08-14 122 views
1

我有一个表“数据”,其中大约100,000,000条记录。 我已经添加了一个新的列“batch_id”(整数)。MySQL更新变得非常缓慢对表结束

在应用程序层上,我正在更新每个10,000,000条记录的10000个记录的batch_id(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

“~30秒”为前10,000行?什么是'result_id'? –

+0

可以请你为SQL显示一个解释吗? –

+0

这是什么语言? Ruby似乎有些模糊,但它使用全局变量。 – tadman

回答

2

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

因此,而不是一个索引batch_id会有所帮助。

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

但应该更容易创建batch_id作为autonumeric列

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

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

+0

只是为了清理潜在的混乱: 1)我已经在BATCH_ID指数 2)BATCH_ID不是主键(id是主键) 关于“可以在主键上的索引?”,我想知道是否查询“回退”在ID /主键上(根据我的知识,mysql仍然必须扫描主键索引上的整个表格,而不是正常指标) –

+0

然后林不知道是什么问题。也许更新索引需要很长时间。您应该比较早期快速更新和稍后更新的[ANALYZE](http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) 。其他选项是创建一个新表,然后替换旧表。 –

0

你有没有在表中的单调递增的ID?而“批”的所有行都有'连续'IDS?然后,请不要将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