繁体   English   中英

mysql - 从InnoDB删除行非常慢

[英]mysql - Deleting Rows from InnoDB is very slow

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

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

Delete from fuelinjection_stroke where DBID < 1000000;

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

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

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

   DELETE FROM fuelinjection_stroke WHERE DBID < 1000000 LIMIT 10000;

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

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

如果没有,您可以适应新的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)

参考文献:

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

MySQL服务器设置调整

MySQL性能优化基础知识

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

你有什么指数?

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

如果有的话,我会删除索引,执行删除操作,然后重新添加索引。 它会快得多,(我想)。

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

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;

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

您的数据库可能正在检查需要在外键中修改的记录(级联,删除)。

但是I-Conica的答案是一个好点(+1)。 在完成100000次期间删除单个记录并更新大量索引的过程效率低下。 只需删除索引,删除所有记录并再次创建。

当然,检查数据库中是否存在任何类型的锁定。 一个用户或应用程序可以锁定记录或表,您的查询将等待用户释放资源或达到超时。 检查数据库是否正在执行实际工作或只是等待的一种方法是将连接设置--innodb_lock_wait_timeout参数设置为几秒钟。 如果它至少失败,你知道查询是正常的,你需要找到并重新发布该锁。 锁的示例是从XXX中选择*用于更新和未通信的事务。

对于这样的长桌,我宁愿使用MYISAM,特别是如果不需要很多交易的话。

我不知道确切的问题。 但是写另一种删除这些行的方法,请试试这个。

delete from fuelinjection_stroke where DBID in
(
    select top 1000000 DBID  from fuelinjection_stroke 
    order by DBID asc
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM