假设有一个表(syslogs)有1000万条记录,需要在业务不停止的情况下删除其中statusid=1的所有记录,差不多有600万条, 直接执行 DELETE FROM syslogs WHERE statusid=1 会发现删除失败,因为lock wait timeout exceed的错误。
因为这条语句所涉及的记录数太多,因此我们通过LIMIT参数分批删除,比如每10000条进行一次删除,那么我们可以利用 MySQL这样的语句来完成:
DELETE FROM syslogs WHERE status=1 ORDER BY statusid LIMIT 10000;
如果要用order by 必须要和 limit 联用,否则被优化掉。然后分多次执行就可以把这些记录成功删除。
注意:
执行大批量删除的时候注意要使用上limit。因为如果不用limit,删除大量数据很有可能造成死锁。
如果delete的where语句不在索引上,可以先找主键,然后根据主键删除数据库。
平时update和delete的时候最好也加上limit 1 来防止误操作。
1.删除大表的部分数据
一个表有1亿6000万的数据,有一个自增ID。最大值就是1亿6000万,需要删除大于250万以后的数据,有什么办法可以快速删除?
看到mysql文档有一种解决方案:http://dev.mysql.com/doc/refman/5.0/en/delete.html
If you are deleting many rows from a large table, you may exceed the lock table size for an InnoDB table. To avoid this problem, or simply to minimize the time that the table remains locked, the following strategy (which does not use DELETE at all) might be helpful:
Select the rows not to be deleted into an empty table that has the same structure as the original table:
INSERT INTO t_copy SELECT * FROM t WHERE ... ;
Use RENAME TABLE to atomically move the original table out of the way and rename the copy to the original name:
RENAME TABLE t TO t_old, t_copy TO t;
Drop the original table:
DROP TABLE t_old;
删除大表的多行数据时,会超出innod block table size的限制,最小化的减少锁表的时间的方案是:
1、选择不需要删除的数据,并把它们存在一张相同结构的空表里
2、重命名原始表,并给新表命名为原始表的原始表名
3、删掉原始表
在My SQL数据库使用中,有的表存储数据量比较大,达到每天三百万条记录左右,此表中建立了三个索引,这些索引都是必须的,其他程序要使用。由于要求此表中的数据只保留当天的数据,所以每当在凌晨的某一时刻当其他程序处理完其中的数据后要删除该表中昨天以及以前的数据,使用delete删除表中的上百万条记录时,MySQL删除速度非常缓慢,每一万条记录需要大概4分钟左右,这样删除所有无用数据要达到八个小时以上,这是难以接受的。
查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的,于是删除掉其中的两个索引后测试,发现此时删除速度相当快,一百万条记录在一分钟多一些,可是这两个索引其他模块在每天一次的数据整理中还要使用,于是想到了一个折中的办法:
在删除数据之前删除这两个索引,此时需要三分钟多一些,然后删除其中无用数据,此过程需要不到两分钟,删除完成后重新创建索引,因为此时数据库中的数据相对较少,约三四十万条记录(此表中的数据每小时会增加约十万条),创建索引也非常快,约十分钟左右。这样整个删除过程只需要约15分钟。对比之前的八个小时,大大节省了时间。
表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放!!!
这种删除表的优点是:支持回滚,后悔了可以恢复数据,可以删除单条数据
缺点:删除效率比较低
delete from user; //删除user表中的数据,但是这种删除数据的方式有点慢。
效率比较高,表被一次截断,物理删除
优点:快速,不走事务,不会锁表,也不会产生大量日志写入日志文件
缺点:不支持回滚,只能删除表中所有数据,不能删单条数据
如果说公司项目里面有一张大表,数据非常多,几亿条记录:
删除的时候,使用delete,也许执行一个小时才能删除完,效率极其低;
可以选择使用truncate删除表中的数据。只需要不到1s的时间就能删除结束,效率较高。
但是使用truncate之前,必须仔细询问客户是否真的需要删除,并警告删除之后不可恢复!!!
truncate table user; //删除user表中的数据,快速。
drop table 表名;// 删除表,不是删除表中的数据
truncate和delete是删除表中的数据,表还在。
参考文章
mysql批量删除大量数据
MySQL中快速删除表中的数据
Mysql 大批量删除数据(解决方案)
MySQL删除大批量数据