V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
dreamkuo
V2EX  ›  问与答

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

  •  
  •   dreamkuo · 2023-04-12 21:59:42 +08:00 · 920 次点击
    这是一个创建于 609 天前的主题,其中的信息可能已经有所发展或是发生改变。
    两个业务,
    一个业务多线程插入 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.

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

    如果是先插入后读取删除
    那其实没啥好说的。
    dreamkuo
        4
    dreamkuo  
    OP
       2023-04-13 00:51:01 +08:00
    @imv2er 感谢你的解答 你的意思是把单独维护一个主键的 消息队列. 读取数据去消息队列里面取主键,然后再取数据,我研究一下这个方案
    谢谢
    dreamkuo
        5
    dreamkuo  
    OP
       2023-04-13 00:53:36 +08:00
    @imv2er 非常感谢 ,感觉这个方案可行性很高,谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5438 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 01:48 · PVG 09:48 · LAX 17:48 · JFK 20:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.