多字段联合查询
- 创建原则:按照查询条件中字段的使用频率和选择性,从高到低排列创建联合索引。例如,如果查询经常是
{field1: value1, field2: value2}
,且 field1
的选择性高于 field2
,则创建 {field1: 1, field2: 1}
的索引(1 表示升序, -1 表示降序)。
- 优化方法:避免冗余索引,确保联合索引覆盖尽可能多的查询场景。同时,要注意索引字段顺序,因为 MongoDB 索引遵循最左前缀原则。例如,对于索引
{field1: 1, field2: 1}
,可以支持 {field1: value1}
和 {field1: value1, field2: value2}
的查询,但不支持 {field2: value2}
的查询(除非单独为 field2
创建索引)。
范围查询
- 创建原则:对于范围查询(如
$gt
, $lt
, $gte
, $lte
),如果查询条件中同时有等式条件和范围条件,等式条件字段在前,范围条件字段在后创建联合索引。例如,查询为 {field1: value1, field2: {$gt: value2}}
,则创建 {field1: 1, field2: 1}
的索引。
- 优化方法:范围查询时,索引字段顺序很关键。另外,尽量避免在范围查询字段后接其他非范围查询字段,因为范围查询后索引的最左前缀原则可能失效。例如,
{field1: 1, field2: 1}
索引,在 {field1: value1, field2: {$gt: value2}, field3: value3}
查询中,field3
可能无法利用索引。
使用 explain 方法分析索引有效性
- 执行方式:在查询语句后调用
explain()
方法,例如 db.collection.find({field1: value1, field2: value2}).explain()
。
- 分析结果:
- queryPlanner.winningPlan.inputStage.indexName:查看实际使用的索引名称,如果显示
COLLSCAN
则表示全表扫描,未使用索引,需要优化索引。
- queryPlanner.winningPlan.inputStage.direction:判断索引扫描方向,
forward
或 backward
,确保索引使用方向正确。
- executionStats.executionTimeMillis:查询执行时间,通过调整索引,观察此值的变化,评估索引优化效果。
示例
- 多字段联合查询示例:
假设集合
users
有 name
和 age
字段,经常查询 name
为特定值且 age
为特定值的用户。
// 创建联合索引
db.users.createIndex({name: 1, age: 1});
// 查询并分析
db.users.find({name: "John", age: 30}).explain();
- 范围查询示例:
假设查询
age
大于 30 岁的用户。
// 创建索引
db.users.createIndex({age: 1});
// 查询并分析
db.users.find({age: {$gt: 30}}).explain();