mongodb 删除性能问题请教

2020-08-17 10:30:32 +08:00
 dtgxx

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


使用 python 脚本 pymongo delete_many


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


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


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

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

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

我之前硬盘三年预计寿命到了之后自动限制写入速度,不影响读取速度
dtgxx
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
2020-08-17 15:15:54 +08:00
@libook 奥我理解你的意思了,我直接去 find2000 个指定的 objectid 试试速度去。
matrix67
2020-08-17 15:17:25 +08:00
@dtgxx #9 不应该只看带宽,还要看下 iops 是否有瓶颈
opengps
2020-08-17 15:18:26 +08:00
有个物理约束:硬盘,你用的啥硬盘?
如果是云服务器的普通虚拟硬盘,那么他的 io 往往只有普通 5400 转硬盘的十分之一左右
laminux29
2020-08-17 15:47:46 +08:00
@dtgxx 我的意思是,你对 MongoDB 带源码调试。不是调试你的程序,而是调试 MongoDB 。
dtgxx
2020-08-17 15:48:27 +08:00
@libook 通过 2000 个 objectid 直接查询,瞬间就查询到结果了。应该是具体删出的时候,非常的慢。
@matrix67 刚看了下 iops,很有道理,但是刚刚找了一下,没有对 iops 的查询工具,您有推荐吗?
@opengps 是希捷的 7200 转 6T 盘,物理服务器
libook
2020-08-17 16:03:39 +08:00
@dtgxx 你用你的 Python 脚本找出 2000 个待删除的 ID,再手工使用 deleteMany 在 MongoShell 里执行试试,如果依然很快,就基本能说明是 Python 脚本执行效率的问题了。
慢的话就看看这个集合是不是索引太多,以及看看 IOPS,可以试试 iostat 指令
dtgxx
2020-08-17 16:12:15 +08:00
@libook #18 试了一下,deleteMany 比较慢,大部分时间都消耗在这里。
leopod1995
2020-08-18 11:51:39 +08:00
读应该不是问题,应该是写性能太差。
性能问题应该出在写 Oplog 上, 可以考虑{ writeConcern: { w: 0}}

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

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

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

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

© 2021 V2EX