MySQL 更新在接近表末尾时变得非常慢

标签 mysql performance innodb query-performance

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

在应用程序层,我以 10,000 条记录为批处理更新 100,000,000 条记录中的每条记录的 batch_id(对于 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 秒。我现在已经完成了 table 的一半,并且速度变得越来越慢。目前,相同的语句大约需要 10 分钟(!)。它已经达到了不再可行的地步,因为以当前的速度更新整个表需要一个多月的时间。

我可以做些什么来加速它,为什么 MySQL 在接近表末尾时变得更慢? 主键索引有帮助吗?

最佳答案

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

关于MySQL 更新在接近表末尾时变得非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45677272/

相关文章:

java - 使用 HttpURLConnection 在 Android 中更新 mySql 表

php - 在 PHP 7 的 foreach 中通过引用传递值对性能真的有用吗

mysql - Innodb全文提升速度

mysql - 安装Mysql 5.7失败

mysql - 从 shell 脚本将表导出为 mysql 中的 csv

performance - 每个时钟性能。 - 我可以对同一条指令使用不同的寄存器吗?

mysql - 将行的子集从一个表复制到另一个表,过滤两列

mysql - 数据库大于 RAM 的 MySQL 上的 "innodb_buffer_pool_size"

mysql - 创建 MySQL 触发器的 SQL 语法错误

php - mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows等…期望参数1为资源或结果