【问题标题】:MySQL updates getting very slow towards end of the tableMySQL 更新在表末尾变得非常缓慢
【发布时间】:2018-01-22 10:54:55
【问题描述】:

我有一个表“数据”,其中包含大约 100,000,000 条记录。 我已经向它添加了一个新列“batch_id”(整数)。

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

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

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 在表的末尾变得越来越慢? 主键索引有帮助吗?

【问题讨论】:

  • 前 10,000 行 “~30 秒”? result_id 是什么?
  • 你能解释一下 SQL 吗?
  • 这是什么语言?看起来有点 Ruby,但它使用全局变量。
  • @PaulSpiegel - 抱歉打错了,result_id == batch_id
  • 我遇到了完全相同的问题,即显着减少了 mySQL 的更新时间。我也有 100,000,000 条记录要更新。我不明白为什么系统会因为我根据主键进行更新而变慢,并且表大小始终保持不变

标签: mysql performance innodb query-performance


【解决方案1】:

表中是否有单调递增的 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

【讨论】:

    【解决方案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)我已经在batch_id上有一个索引2)batch_id不是主键(id是主键)关于“主键上的索引可以帮助吗? ”,我想知道查询是否“回退”在 id/主键上(据我所知,mysql 仍然必须在主键索引上扫描整个表,而不是普通索引)
    • 那么我不确定是什么问题。也许更新索引需要很长时间。您应该比较早期快速更新和后期较慢更新的ANALYZE。另一种选择是创建一个新表,然后替换旧表。
    猜你喜欢
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 2015-08-22
    • 2016-01-26
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多