面试题答案
一键面试设计步骤
- 分析查询需求:明确多字段查询场景中涉及的字段,例如查询语句为
db.collection.find({field1: value1, field2: value2})
,这里的field1
和field2
就是需要关注的字段。 - 创建复合索引:根据查询中字段的使用顺序来创建复合索引。例如上述查询,应创建
db.collection.createIndex({field1: 1, field2: 1})
。索引中字段的顺序很关键,要按照查询条件中字段出现的顺序(如果查询条件中有AND
关系)或者按照过滤性更强的字段在前的原则。 - 验证覆盖索引:执行查询时,可以通过
explain()
方法查看查询计划。若在查询计划的winningPlan.inputStage.indexBounds
中有相应的索引范围,且winningPlan.inputStage.name
为IXSCAN
,同时cursor
为IndexCursor
,并且返回的字段都包含在索引中,就说明实现了覆盖索引。
可能遇到的问题及解决方案
- 索引字段顺序问题:如果复合索引中字段顺序与查询中字段顺序不匹配,可能无法使用覆盖索引。解决方案是严格按照查询条件中字段的使用顺序(特别是
AND
条件下)来创建复合索引。 - 索引维护成本:复合索引会占用额外的磁盘空间和增加写入操作的开销。解决方案是定期评估索引的使用情况,删除不再使用的索引。可以使用
db.collection.totalIndexSize()
查看索引占用空间,使用db.currentOp()
观察写入操作对性能的影响。 - 查询字段不在索引中:若查询结果中包含不在复合索引中的字段,就无法实现覆盖索引。解决方案是尽量将查询需要返回的字段都包含在复合索引中,但要注意避免索引过于庞大。若无法将所有字段包含在索引中,可以考虑投影只返回索引中的字段。