面试题答案
一键面试1. 覆盖索引的概念
覆盖索引指的是查询所需的所有数据都可以从索引本身获取,而无需再去读取文档。在MongoDB中,索引是一种特殊的数据结构,它以某种特定顺序存储文档中字段的值,便于快速查找。当索引包含了查询所需要的所有字段时,MongoDB可以直接从索引中提取数据返回给客户端,而不必再通过索引定位到文档然后读取文档内容,这样可以极大地减少I/O操作,提高查询性能。
2. 判断查询是否利用了覆盖索引
可以使用explain()
方法来判断查询是否利用了覆盖索引。例如,假设有一个集合students
,包含字段name
、age
和grade
,并在name
和age
上建立了复合索引{name: 1, age: 1}
。
// 查询语句
db.students.find({name: "Alice", age: 20}, {name: 1, age: 1, _id: 0})
// 使用explain查看执行计划
db.students.find({name: "Alice", age: 20}, {name: 1, age: 1, _id: 0}).explain("executionStats")
在explain
的输出结果中,如果"stage": "IXSCAN"
(表示使用了索引扫描)且"indexOnly": true
,则说明该查询利用了覆盖索引。
3. 实际开发中利用覆盖索引提升查询性能
假设在一个电商系统中,有一个products
集合,包含字段productName
、price
、description
等。如果经常需要根据productName
查询price
,可以这样设计:
- 创建索引:
db.products.createIndex({productName: 1, price: 1})
- 编写查询:
db.products.find({productName: "iPhone 14"}, {productName: 1, price: 1, _id: 0})
这样的查询就可以利用覆盖索引,因为索引中包含了查询所需的productName
和price
字段,无需再读取文档。
4. 排序操作与覆盖索引
如果查询中包含排序操作,覆盖索引仍然可以生效,但有一定条件。
- 条件满足时生效:当排序字段包含在覆盖索引中,且索引顺序与排序顺序一致时,覆盖索引可以生效。例如,集合
users
有字段name
、age
,建立索引{name: 1, age: 1}
。查询db.users.find({name: /^A/}, {name: 1, age: 1, _id: 0}).sort({name: 1, age: 1})
,由于排序字段name
和age
都在索引中且顺序与索引一致,所以覆盖索引生效。 - 条件不满足时失效:如果排序字段不在覆盖索引中,或者索引顺序与排序顺序不一致,覆盖索引可能失效。比如查询
db.users.find({name: /^A/}, {name: 1, age: 1, _id: 0}).sort({age: -1})
,虽然age
在索引中,但索引顺序是{name: 1, age: 1}
,而排序是{age: -1}
,此时覆盖索引可能无法生效,MongoDB可能需要读取文档来进行排序操作。