V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
dtgxx
V2EX  ›  MongoDB

mongodb 删除性能问题请教

  •  
  •   dtgxx · 2020-08-17 10:30:32 +08:00 · 5770 次点击
    这是一个创建于 1557 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大佬们,目前我在删除一些 mongo 的数据,根据 ObjectID 删除,每一次删除 2000 条。


    使用 python 脚本 pymongo delete_many


    但是性能上很差,每秒删除在几十到几百条数据。


    我看内存、磁盘、cpu 的压力都非常小。。不知道问题到底出在哪了。。有什么好办法可以提高删除的效率吗?


    不是软删除,是真正按数据删掉。

    第 1 条附言  ·  2020-08-17 18:28:50 +08:00

    感谢大家,瓶颈应该是在IO。


    tps比较高。


    Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda 0.81 14.61 20.98 448477 643872 sdb 284.46 2089.13 3099.71 64121884 95139952 sdc 0.02 0.15 0.00 4485 32 dm-0 0.62 12.52 11.83 384408 363246 dm-1 2.50 1.04 9.02 31880 276920 dm-2 0.02 0.12 0.07 3634 2048


    网上关于tps的科普稍微有点少,我使用的是7200转的希捷sata盘,284的tps应该是到瓶颈了。

    第 2 条附言  ·  2020-08-17 18:29:48 +08:00
    iostat

    ---

    Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
    sda 0.81 14.61 20.98 448477 643872
    sdb 284.46 2089.13 3099.71 64121884 95139952
    sdc 0.02 0.15 0.00 4485 32
    dm-0 0.62 12.52 11.83 384408 363246
    dm-1 2.50 1.04 9.02 31880 276920
    dm-2 0.02 0.12 0.07 3634 2048
    21 条回复    2020-08-18 14:57:51 +08:00
    rrfeng
        1
    rrfeng  
       2020-08-17 10:49:36 +08:00
    看下监控 db.serverStatus 里关于 wiredTigerCache 的部分
    laminux29
        2
    laminux29  
       2020-08-17 13:50:49 +08:00
    带源码调试一下,不就知道瓶颈在哪了嘛。
    libook
        3
    libook  
       2020-08-17 13:56:07 +08:00
    把脚本发上来看一看
    Vegetable
        4
    Vegetable  
       2020-08-17 13:57:37 +08:00
    你 objectid 哪来的?查出来的?
    dtgxx
        5
    dtgxx  
    OP
       2020-08-17 14:13:34 +08:00
    @rrfeng 感谢,没有看出有什么异常的情况。
    @laminux29 应该不是应用层的问题,瓶颈不在代码上。
    @Vegetable 因为数据量比较大,之前把 ObjectID 都整理到另一个集合了。从一个集合查询,然后删除。
    @libook datacol.delete_many({'_id': {'$in': dup_list}})
    瓶颈应该是在从百亿数据里面查询对应的 objectid,然后删除。真的是非常慢。。一秒就能查询到 300 左右然后删除掉。
    dtgxx
        6
    dtgxx  
    OP
       2020-08-17 14:13:55 +08:00
    也尝试了多线程、多进程的方式,性能就变更慢了。。
    asilin
        7
    asilin  
       2020-08-17 14:47:17 +08:00
    可以确定是磁盘 IO 瓶颈,具体可以用 iostat 命令看下,会发现 IO 使用率接近 100%。
    liprais
        8
    liprais  
       2020-08-17 14:49:40 +08:00
    100 亿数据还不如先导出再导入呢
    dtgxx
        9
    dtgxx  
    OP
       2020-08-17 14:52:42 +08:00
    @asilin #7 用于删除脚本的 io 确实是接近 100%,但是服务器磁盘的吞吐才不足 10M 每秒,请教下,进程的 io 接近 100%是指给这个进程分配的 io 使用量被占满了吗?我看远不到磁盘的吞吐量。
    @liprais 没太理解
    libook
        10
    libook  
       2020-08-17 14:57:00 +08:00
    _id 通常是默认有索引的,所以你得确认是查询速度慢,还是删除的时候写速度慢。这个你可以在数据库本地的 MongoShell 尝试 find 2000 条数据,看看执行时间多少。如果很慢的话,看看索引是否正常,以及是否单个索引太大以至于无法完全缓存在内存里。如果很快的话,就看看是不是写速度问题。
    通常来说,有索引查询会快,但是索引越多,写速度就越慢,所以得看看这个 Collection 上是不是索引太多了。

    如果在数据库本地的 MongoShell 里测试性能很好,就看看是不是 Python 脚本执行效率的问题或网络的问题。
    misaka19000
        11
    misaka19000  
       2020-08-17 14:58:22 +08:00
    @dtgxx #9 你什么硬盘?是不是时间太长了导致硬盘限制写入了

    我之前硬盘三年预计寿命到了之后自动限制写入速度,不影响读取速度
    dtgxx
        12
    dtgxx  
    OP
       2020-08-17 15:14:51 +08:00
    @libook 感谢分享思路。我目前从集合 A 查询 2000 条 ObjectID 加上处理这些 ID 大约在 500ms 左右,处理后的 ObjectID 大约剩下 1500 条左右,然后开始执行 集合 B.delete_many({'_id': {'$in': dup_list}}) ,就非常的慢。我现在不太好定位具体是在集合 B 查询 ObjectID 太慢,还是查询后删除太慢。。这个语句是应该是在一个事务里的?
    @misaka19000 硬盘还是比较新的,使用了没几个月,应该不是写性能的限制,之前拷贝数据的时候,能到到 200M/s 的吞吐。 不过目前也有个问题没查出来,就是用 iotop,进程的 io 百分比接近 100%,但是实际上磁盘的吞吐只有几 M 而已,不知道这个百分比是怎么计算的。
    dtgxx
        13
    dtgxx  
    OP
       2020-08-17 15:15:54 +08:00
    @libook 奥我理解你的意思了,我直接去 find2000 个指定的 objectid 试试速度去。
    matrix67
        14
    matrix67  
       2020-08-17 15:17:25 +08:00   ❤️ 1
    @dtgxx #9 不应该只看带宽,还要看下 iops 是否有瓶颈
    opengps
        15
    opengps  
       2020-08-17 15:18:26 +08:00
    有个物理约束:硬盘,你用的啥硬盘?
    如果是云服务器的普通虚拟硬盘,那么他的 io 往往只有普通 5400 转硬盘的十分之一左右
    laminux29
        16
    laminux29  
       2020-08-17 15:47:46 +08:00
    @dtgxx 我的意思是,你对 MongoDB 带源码调试。不是调试你的程序,而是调试 MongoDB 。
    dtgxx
        17
    dtgxx  
    OP
       2020-08-17 15:48:27 +08:00
    @libook 通过 2000 个 objectid 直接查询,瞬间就查询到结果了。应该是具体删出的时候,非常的慢。
    @matrix67 刚看了下 iops,很有道理,但是刚刚找了一下,没有对 iops 的查询工具,您有推荐吗?
    @opengps 是希捷的 7200 转 6T 盘,物理服务器
    libook
        18
    libook  
       2020-08-17 16:03:39 +08:00
    @dtgxx 你用你的 Python 脚本找出 2000 个待删除的 ID,再手工使用 deleteMany 在 MongoShell 里执行试试,如果依然很快,就基本能说明是 Python 脚本执行效率的问题了。
    慢的话就看看这个集合是不是索引太多,以及看看 IOPS,可以试试 iostat 指令
    dtgxx
        19
    dtgxx  
    OP
       2020-08-17 16:12:15 +08:00
    @libook #18 试了一下,deleteMany 比较慢,大部分时间都消耗在这里。
    leopod1995
        20
    leopod1995  
       2020-08-18 11:51:39 +08:00   ❤️ 1
    读应该不是问题,应该是写性能太差。
    性能问题应该出在写 Oplog 上, 可以考虑{ writeConcern: { w: 0}}
    dtgxx
        21
    dtgxx  
    OP
       2020-08-18 14:57:51 +08:00
    @leopod1995 #20 开启这个参数之后,速度有一点提升,不过影响不是很大,也是非常感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3380 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 10:58 · PVG 18:58 · LAX 02:58 · JFK 05:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.