本文将会介绍 MongoDB 复合索引的概念,以及如何创建复合索引。
复合索引(compound index)是指基于多个字段的索引,通常可以用于优化匹配多个字段的查询。
复合索引同样可以使用 createIndex() 方法创建,语法如下:
db.collection.createIndex({field1: type,field2: type,field3: type,...
});
其中,field1、field2、field3 都是字段;type 代表了类型,1 表示索引中的数据按照升序排列,-1 表示按照降序排列。
ℹ️MongoDB 复合索引最多包含 32 个字段。
复合索引中的字段顺序至关重要。如果一个复合索引包含字段 field1、field2,索引首先按照 field1 进行排序,如果 field1 相同,再按照 field2 排序。
复合索引遵循最左匹配原则。例如,一个复合索引包含字段 field1、field2,可以支持以下查询优化:
但是,它不支持基于字段 field2 的查询优化。
首先,我们为集合 movies 创建一个基于 Title 以及 Release Date 的复合索引:
db.movies.createIndex({ Title: 1, 'Release Date': 1 })'Title_1_Release Date_1'
然后查找名称包含 batman,并且在 2005 年 1 月 15 日发行的电影:
db.movies.find({Title: /batman/i, "Release Date": 'Jun 15 2005'}).explain('executionStats');...inputStage: {stage: 'IXSCAN',filter: {Title: BSONRegExp("batman", "i")},nReturned: 1,executionTimeMillisEstimate: 5,works: 3180,advanced: 1,needTime: 3178,needYield: 0,saveState: 3,restoreState: 3,isEOF: 1,keyPattern: {Title: 1,'Release Date': 1},indexName: 'Title_1_Release Date_1',
...
查询使用了索引 Title_1_Release Date_1,而不是扫描整个集合。
然后查找名称包含 batman 的电影:
db.movies.find({Title: /batman/i}).explain('executionStats');...inputStage: {stage: 'IXSCAN',filter: {Title: BSONRegExp("batman", "i")},nReturned: 6,executionTimeMillisEstimate: 0,works: 3192,advanced: 6,needTime: 3185,needYield: 0,saveState: 3,restoreState: 3,isEOF: 1,keyPattern: {Title: 1,'Release Date': 1},indexName: 'Title_1_Release Date_1',
...
以上查询只匹配了 Title,优化器仍然能够使用复合索引进行优化。
然后查找在 2005 年 1 月 15 日发行的电影:
db.movies.find({"Release Date": 'Jun 15 2005'}).explain('executionStats');...executionStages: {stage: 'COLLSCAN',filter: {'Release Date': {'$eq': 'Jun 15 2005'}},nReturned: 1,
...
这种情况下,查询优化器无法使用复合索引,而是通过扫描整个集合(COLLSCAN)查找数据。