数据库批量读取并删除如何效率最高

2023-04-12 21:59:42 +08:00
 dreamkuo
两个业务,
一个业务多线程插入 N 条数据
另一个业务,多线程读取并删除 N 条数据 /或者使用 update 先修改数据加上唯一标签,然后读取,然后删除数据(update xxxx set use =1 token = uuid where use = 0 limit 100)
这两种读取并删除的方式
第一种方式要使用 for update 锁. 效率很低.
第二种方式使用 update 先修改数据,然后再删除数据,不用加锁,但是在多线程情况下效率更低,而且线程之间不会队列执行, 有的线程很快执行,有的会超时.
我考虑原因, 是 mysql 每个线程都会去数据的相同固定部分抓取数据
导致不管是 select 还是 update 都会冲突.
有没有更快的方式来实现这个功能呢? 什么类型的数据库,或者什么 sql 方案.

对 use 已经加索引了 但是加索引的作用不大, 我感觉 use 不是 0 就是 1 加了索引只是排除掉 use=1 的部分,这部分数据很少,use=0 的数据有几百万条. 但是 mysql 只会去头部取数据,导致冲突, 能不能让 mysql 每个任务都随机位置取数据呢.


业务需要统计数量等要求.所以不能用 list.

本人新手,表达能力不好,专业术语也不知道,实在抱歉,希望不吝赐教.
742 次点击
所在节点    问与答
5 条回复
iBugOne
2023-04-12 22:01:02 +08:00
有没有可能你需要的东西不是 RDBMS ,而是一个消息队列
dreamkuo
2023-04-12 22:08:01 +08:00
@iBugOne
感谢你的解答 ,我觉得也是,但是还有一些无法代替的功能,
比如说统计 use=1 use=0 的各自数量,
还有对于 use=1 的数据,修改为 use=0 (相当于回滚获取的数据.)
imv2er
2023-04-12 22:55:21 +08:00
如果是边插入边读取删除
插入的线程在插入完成后将主键值传递给读取删除的线程。
插入线程每次做批量插入,一次性提交。传递给后续线程也是一批一批的
读取删除的线程每次操作也是一个事务中的批量操作
无论删除和更新都要用主键作为 where 条件。
主键的传递可以考虑使用消息队列确保异常重启时不会遗漏没有读取的那部分。

如果是先插入后读取删除
那其实没啥好说的。
dreamkuo
2023-04-13 00:51:01 +08:00
@imv2er 感谢你的解答 你的意思是把单独维护一个主键的 消息队列. 读取数据去消息队列里面取主键,然后再取数据,我研究一下这个方案
谢谢
dreamkuo
2023-04-13 00:53:36 +08:00
@imv2er 非常感谢 ,感觉这个方案可行性很高,谢谢

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

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

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

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

© 2021 V2EX