我有一个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)
并继续执行它直到删除所有内容
你有什么指标?
我认为你的问题是删除在每次迭代时重建索引。
我会删除索引(如果有),执行删除,然后重新添加索引。它会快得多,(我认为)。
你是否被剥夺了空间?停工时间不可能吗?
如果没有,您可以适应新的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)
参考文献:
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 万行。