mysql delete 操作速度慢!

2021-06-16 10:26:31 +08:00
 aeo13

1 、由于业务需要,需要对接第三方的数据,如某个用户访问时会执行同步接口,之后按顺序对数据执行删除、修改和新增。目前增改都没有问题,但是删除会很慢,导致每分钟都会有好几条慢日志生成。

2 、该表数据目前是三百多 W 。

3 、目前的删除 sql 是 DELETE FROM order WHERE order_id IN () AND status IN (),order_id 有几个到几十个不等,status 有几个。

阿里云 RDS 的慢日志(截取某一分钟): https://imgur.com/S5N6w2v EXPLAIN 结果: https://imgur.com/dhCSC3a

4 、所作尝试 1 )改用 select 所有主键 id 再 in 删除主键 id,发现执行时间更长 2 )改用 delete where userid = 用户 id,发现执行时间更长 3 )改用循环删除操作,CPU 顶不住

6679 次点击
所在节点    MySQL
37 条回复
duanxianze
2021-06-16 10:29:37 +08:00
互联网公司,从不真正删除任何数据,打个标记也就行了,mysql 的数据结构删除本来就是慢,非要删除就每晚空闲的时候对打了标记的统一删除
AngryPanda
2021-06-16 10:30:03 +08:00
4.3 + 异步删除?
sunnyday123
2021-06-16 10:40:24 +08:00
order_id IN () AND status IN (): IN 会让索引失效,应该是走了全表扫描.尝试去掉 in,status 和 order_id 建一个联合索引
SmartKeyerror
2021-06-16 10:40:26 +08:00
InnoDB 存储引擎的话,删除数据可能会造成 B+Tree 中存在数据空洞,如果不进行表整理的话,随着频繁的插入和删除,.ibd 文件可能会越来越大,导致 delete from 执行时扫描了许多原本已经删除的行。最好方法当然是使用 is_deleted 标志位,如果一定要进行物理删除的话,可以在删除之前将可能被删除的数据 select 到 buffer pool 中,然后在进行删除,相当于做了一层缓存
lostSoul
2021-06-16 10:42:26 +08:00
还真有 delete 的? 我们都是 update 的 如果数据太多 更新也会慢 上队列异步慢慢慢处理吧
aeo13
2021-06-16 10:57:20 +08:00
@sunnyday123 先查询出主键 id 的集合再 in 主键删除都不行。。
aeo13
2021-06-16 11:01:14 +08:00
@SmartKeyerror 请问你指的是表的碎片率?
sunnyday123
2021-06-16 11:02:35 +08:00
@aeo 只要有 in 索引就失效,orde_id =id and status in() 还是全表扫描,explain 看下扫描行数吧.
aeo13
2021-06-16 11:04:06 +08:00
@sunnyday123 但是我在 4.2 也尝试使用过 where userid=用户 id 的条件,userid 是有设置索引,同样也很慢
SmartKeyerror
2021-06-16 11:04:42 +08:00
@aeo13 对,从 EXPLAIN 的结果上来看,应该不至于这么慢才对,而且数据只有 300 万
aeo13
2021-06-16 11:05:47 +08:00
@SmartKeyerror 查看了一下阿里云的表分析,表空间 3.04 GB,索引空间 943.88 MB,碎片率是 0.19%
MoYi123
2021-06-16 11:20:33 +08:00
看看触发器? 我之前有个 nt 同事,会在表 delete 的时候,把整个表备份一次。
aeo13
2021-06-16 11:22:59 +08:00
@MoYi123 没有创建任何触发器哦
CEBBCAT
2021-06-16 11:26:02 +08:00
你这个 EXPLAIN 是 EXPLAIN 的按主键删除吧?其他几种删除方法呢?比如你说的 STATUS IN () 的那个。

另外,建表语句可以给一下吗?

如果表上的索引不少,我怀疑删除数据的时候也会被重建索引拖慢速度
aeo13
2021-06-16 11:35:28 +08:00
@CEBBCAT
EXPLAIN 的是 DELETE FROM order WHERE order_id IN () AND status IN ()这个的
建表语句: https://imgur.com/undefined
是的,索引不少,数据空间 2.11 GB,索引空间是 943.88 MB
aeo13
2021-06-16 11:35:53 +08:00
@CEBBCAT 建表语句重新贴一下: https://imgur.com/2Nw4acp
MoGeek
2021-06-16 15:22:49 +08:00
推荐一楼的方法,直接打标识就好。可以定期删除
westoy
2021-06-16 15:32:03 +08:00
打 flag 然后半夜里定时清啊, 哪有生产环境在线硬删数据的......
keepeye
2021-06-16 15:35:17 +08:00
实在不行呢,可以按 status 来遍历删除,这样 order_id 索引大概能生效
DELETE FROM order WHERE order_id IN (?) AND status = 1;
DELETE FROM order WHERE order_id IN (?) AND status = 2;
...
DELETE FROM order WHERE order_id IN (?) AND status = N;
wolfie
2021-06-16 15:39:55 +08:00
@sunnyday123
只要有 in 索引就失效?上面不是贴了 explain 吗。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/783664

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX