咸鱼翻身,还是咸鱼。
原因
线上MongoDB服务器资源报警,查看MongoDB log发现有大量的查询没有走索引。于是添加索引
操作
具体的查询语句列子:
1 | command feeds.content_medium_hismatch command: count { count: "content_medium_hismatch", query: { update_time: { $gte: 1384099200000, $lt: 1384185600000 }, content_type_id: "28" } } planSummary: IXSCAN { content_type_id: 1 } keysExamined:191146 docsExamined:191146 fromMultiPlanner:1 replanned:1 numYields:10767 reslen:44 locks:{ Global: { acquireCount: { r: 21536 } }, Database: { acquireCount: { r: 10768 } }, Collection: { acquireCount: { r: 10768 } } } protocol:op_query 84011ms |
通过MongoDB explain()
1 | repset:PRIMARY> db.content_medium_hismatch.find({ count: "content_medium_hismatch", query: { update_time: { $gte: 1384099200000, $lt: 1384185600000 }, content_type_id: "28" }}).explain() |
于是很鲁莽的添加了索引操作
1 | db.content_medium_hismatch.ensureIndex({update_time: 1, content_type_id: 1}) |
发现时间很长,于是就crtl+c中断操作,在执行登录MongoDB shell 发现操作都堵塞。执行tail -f /data/repset/log/mongod.log
发现
1 | 2019-04-04T16:54:54.984+0800 I INDEX [conn2744778] build index on: feeds.content_medium_hismatch properties: { v: 2, key: { update_time: 1.0, content_type_id: 1.0 }, name: "update_time_1_content_type_id_1", ns: "feeds.content_medium_hismatch" } |
还在执行创建索引操作。经过排查发现。MongoDB 不是和MySQL一样。中断了就不执行了。而且MongoDB 在前台创建索引操作。会把整个服务阻塞。直到索引创建成功,才会放开阻塞。这样操作直接造成了业务不可用状态,时间整整87分钟。鲁莽惹的祸。
总结
当系统已有大量数据时,创建索引就是个非常耗时的活,我们可以在后台执行,只需指定”backgroud: true”即可。
1 | db.content_medium_hismatch.ensureIndex({update_time: 1, content_type_id: 1}, {backgroud: true}) |
回顾
最后在看一下如此之大的代价创建的索引之后使用的情况
1 | repset:PRIMARY> db.content_medium_hismatch.find({ update_time: { $gte: 1384099200000, $lt: 1384185600000 }, content_type_id: "28" }).explain() |
发现正常走了索引。总算没有白做。可是代价太大了。这个教训告诉我,在不熟悉的数据库操作一定要慎重。针对线上操作,一定要再三慎重。引以为戒!