mysql - 从InnoDB删除行非常慢

use*_*509 12 mysql sql innodb

我有一个mysql数据库约.1 TB的数据.表fuelinjection_stroke有apprx.1.000.000.000行.DBID是每个插入时自动递增1的主键.

我试图使用一个非常简单的语句删除前1.000.000行:

Delete from fuelinjection_stroke where DBID < 1000000;
Run Code Online (Sandbox Code Playgroud)

在我的专用8核Xeon服务器(32 GB内存,SAS存储)上,此查询需要很长时间(> 24小时).

不知道这个过程是否可以加速?

Uri*_*iil 21

我相信你的桌子会被锁定.我遇到了同样的问题,发现可以很快删除10k记录.所以你可能想编写一个简单的脚本/程序,它将按块删除记录.

   DELETE FROM fuelinjection_stroke WHERE DBID < 1000000 LIMIT 10000;
Run Code Online (Sandbox Code Playgroud)

并继续执行它直到删除所有内容

  • 我认为这个解决方案之所以如此有效,是因为事务的大小不会变得很大,因此 MySQL 可以将其放入内存中。否则它必须将所有内容写入磁盘,这会慢得多。 (2认同)

i-C*_*ICA 6

你有什么指标?

我认为你的问题是删除在每次迭代时重建索引。

我会删除索引(如果有),执行删除,然后重新添加索引。它会快得多,(我认为)。

  • 还要禁用对此表的外键引用(如果有)。 (2认同)

jma*_*ail 5

你是否被剥夺了空间?停工时间不可能吗?

如果没有,您可以适应新的INT列长度1并将其默认为1表示"活动"(或任何术语),0表示"非活动".实际上,如果需要,你可以使用0到9作为10种不同的状态.

添加这个新列将花费很多时间,但是一旦结束,只要你从PRIMARY(就像你使用DELETE一样)执行它,你的UPDATE应该是闪电般的快速,并且你没有索引这个新列.

InnoDB在如此庞大的表上删除这么长时间的原因是因为群集索引.它根据您的PRIMARY(或者它找到的第一个UNIQUE ......或者无法找到PRIMARY或UNIQUE的感觉)对您的表进行物理排序,因此当您拉出一行时,它会在物理上重新排序您的整个表格用于速度和碎片整理的磁盘.所以不是DELETE花了这么长时间.删除该行后的物理重新排序.

当您使用默认值创建新的INT列时,空间将被填充,因此当您更新它时,不需要在您的巨大表格中进行物理重新排序.

我不确定你的模式到底是什么,但是使用列的行的状态要比DELETEing快得多; 但是,它需要更多的空间.

尝试设置值:

innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT (for non-windows machine)
innodb_buffer_pool_size=25GB (currently it is close to 21GB)
innodb_doublewrite=0
innodb_support_xa=0
innodb_thread_concurrency=0...1000 (try different values, beginning with 200)
Run Code Online (Sandbox Code Playgroud)

参考文献:

MySQL文档用于描述不同的变量.

MySQL服务器设置调整

MySQL性能优化基础知识

http://bugs.mysql.com/bug.php?id=28382


小智 5

我遇到了同样的问题,我的表有几个我不想删除并重新创建的索引。所以我做了以下事情:

create table keepers
select * from origTable where {clause to retrieve rows to preserve};
truncate table origTable;
insert into origTable null,keepers.col2,...keepers.col(last) from keepers;
drop table keepers;
Run Code Online (Sandbox Code Playgroud)

大约 3 分钟内处理了大约 220 万行。