背景
现有索引
1 | { distributorNo: 1, username: 1 } |
现在有个查询
1 | db.user.findOne({ |
请问这个查询会走哪个索引?
场景
在网上查询资料后发现$or的查询需要每条查询语句都有索引,其实就是MongoDB把每条查询语句都执行了一遍,再将结果合并.
现在用户表有数据3000w+,发现这个查询每次都超时(设置了最长查询时间6秒),所以判断这条查询语句没有走索引,但是按原来的逻辑,{ distributorNo: 1, username: 1 }{ newAppleUserId: 1, distributorNo: 1 }
的索引都有啊.
准备使用.explain(),查看这条查询语句到底是怎么执行的,但是正式数据库数量太多,执行也超时了,就改在本地测试,结果如下
原来MongoDB是先查询了distributorNo,后再进行{distributorNo,username}的查询,在第一步的时候就超时了,因为满足distributorNo条件的数据量占了绝大多数.
解决方案
将查询语句改写
1 | db.user.findOne({ |
也就是不管执行的查询语句是
1 | db.user.findOne({ |
还是
1 | db.user.findOne({ |
都有对应的索引.
部署以后观察,慢查询与超时都消失了
总结
MongoDB 的$or
查询其实就是将每种情况都执行了一次
如果$or
条件之前还有其他条件,MongoDB会先用该条件查询,后再执行$or
里的每一条查询
所以要么将前置条件合并到$or
语句里,要么对前置条件单独建索引