MongoDB中是否应添加布尔字段到索引以降低查询的Examined:Returned Ratio?
嗨,我来帮你拆解这个问题~
首先,先解释下你现在遇到的高比例问题:你当前只有textField的单字段索引,MongoDB会先用这个索引找出所有textField="value"的文档,但之后它得逐个检查这些文档的isField是否为true——这一步是在内存里做的“索引后过滤”,所以才会出现Examined数远大于Returned数的情况(毕竟很多符合textField的文档不符合布尔条件)。
那回到你的核心疑问:把布尔字段加到索引里能不能改善这个比例?答案是肯定的。如果你创建复合索引{textField: 1, isField: 1},MongoDB可以直接在索引层面就筛选出同时满足两个条件的文档,不用再去逐个检查原文档的布尔值,这样Examined数会和Returned数非常接近,比例自然就降下来了。
接下来聊聊你听说的“布尔字段不该索引”这个说法——其实这个结论是有前提的:如果单独给布尔字段建索引,因为它的基数极低(只有true/false两个值),如果数据分布比较均匀(比如各占50%),MongoDB大概率会选择全表扫描而不是用这个索引,这时候单独建索引确实没意义。但你的情况是把布尔字段作为复合索引的后缀,这完全不一样!前面的textField已经把结果集缩小到了一个很小的范围,后面的布尔字段只是在这个小范围里进一步筛选,这种复合索引的效率很高,完全不会有单独建布尔索引的问题。
最后说说要不要做这个优化:你提到当前性能不是问题,那这里可以权衡一下:
- 好处:降低Examined:Returned比例,减少内存中的过滤操作,未来如果数据量增长,这个优化能提前避免性能下降;而且写入时维护这个复合索引的开销很小——毕竟只是在已有textField索引的基础上追加布尔值,你这次update操作修改isField的值时,索引的更新成本也很低。
- 坏处:多一个索引会占用一点点磁盘空间,但在现代存储环境下,这点开销几乎可以忽略。
所以我的建议是:如果未来数据量可能增长,或者你想优化这个查询的执行效率,完全可以创建这个复合索引;就算现在不着急,加了也没什么负面影响。
创建复合索引的命令很简单:
db.yourCollection.createIndex({textField: 1, isField: 1})
备注:内容来源于stack exchange,提问作者biorubenfs

