极速搜索—MongoDB索引查询法

1. MongoDB 索引介绍

MongoDB 是一种灵活而且可扩展的 NoSQL 数据库,具有高度开放的体系结构和放松的一致性模型。MongoDB 的索引是执行高效查询的关键,可以避免遍历整个集合来获取数据。

索引的作用:

提高查询效率

可以创建唯一索引、建立对应关系

可以加速分组和排序操作

2. MongoDB 索引类型

MongoDB 支持主要三种类型的索引:

单键索引

复合索引

多键索引

2.1 单键索引

单键索引是对集合中单个字段的索引。可以通过显式指定该字段或 _id 自动生成的默认索引来创建。

创建单键索引的方法:

db.collection_name.createIndex({ fieldname: 1 })

查询单键索引的方法:

db.collection_name.find({ fieldname: value }).explain('executionStats')

执行上面的查询语句,在输出的执行计划中可以看到使用了单键索引。

2.2 复合索引

复合索引是对集合中多个字段的索引。比如,当你需要经常按照年龄进行排序和分组,同时又需要按照其他字段进行查询时,可以同时为年龄和其他字段创建一个复合索引。

创建复合索引的语法:

db.collection_name.createIndex( { age: -1, fieldname: 1 } )

这里我们创建了一个以 age 为递减顺序的复合索引,同时以 fieldName 字段为递增顺序的索引。

2.3 多键索引

多键索引是针对集合中的数组进行索引。对数组字段创建索引时,MongoDB 将在一个集合中创建一个索引项,每个数组值包含一个新的索引项。

创建多键索引的方法:

db.collection_name.createIndex({ fieldname: "text"})

查询多键索引的方法:

db.collection_name.find( { $text: { $search: "value" } } )

执行上面的查询语句,可以看到返回了包含 value 的所有文档。

3. 索引的使用方法

3.1 explain 方法

如果要知道 MongoDB 是否正在使用索引以及使用哪种索引,请使用 explain 方法。这个方法提供执行计划。

语法:

db.collection_name.find({ fieldname: value }).explain("executionStats")

返回结果:

{

"queryPlanner" : {

"plannerVersion" : 1,

"namespace" : "dbname.collectionname",

"indexFilterSet" : false,

"parsedQuery" : {

"fieldname" : {

"$eq" : value

}

},

"winningPlan" : {

"stage" : "FETCH",

"inputStage" : {

"stage" : "IXSCAN",

"keyPattern" : {

"fieldname" : 1

},

"indexName" : "fieldname_1",

"isMultiKey" : false,

"multiKeyPaths" : {

"fieldname" : [ ]

},

"indexBounds" : {

"fieldname" : [

"[\"value\", \"value\"]"

]

}

}

},

"rejectedPlans" : [ ]

},

"executionStats" : {

"nReturned" : 0,

"executionTimeMillis" : 0,

"totalKeysExamined" : 0,

"totalDocsExamined" : 0,

"executionSuccess" : true,

"executionStages" : {

"stage" : "FETCH",

"nReturned" : 0,

"executionTimeMillisEstimate" : 0,

"works" : 1,

"advanced" : 0,

"needTime" : 0,

"needYield" : 0,

"saveState" : 0,

"restoreState" : 0,

"isEOF" : 1,

"alreadyHasObj" : 0,

"inputStage" : {

"stage" : "IXSCAN",

"nReturned" : 0,

"executionTimeMillisEstimate" : 0,

"works" : 1,

"advanced" : 0,

"needTime" : 0,

"needYield" : 0,

"saveState" : 0,

"restoreState" : 0,

"isEOF" : 1,

"keyPattern" : {

"fieldname" : 1

},

"indexName" : "fieldname_1",

"isMultiKey" : false,

"multiKeyPaths" : {

"fieldname" : [ ]

},

"indexBounds" : {

"fieldname" : [

"[\"value\", \"value\"]"

]

},

"keysExamined" : 0,

"seeks" : 1,

"dupsTested" : 0,

"dupsDropped" : 0

}

}

}

}

在该执行计划中,可以看到索引的使用情况(winngPlan)。在这个例子中,fieldname_1 是一个单键索引。

3.2 hint 方法

hint() 方法可以在查询中指定使用特定的索引。MongoDB 中的 hint() 方法需要使用 $命令,语法如下:

db.collection_name.find({}).hint({ indexname: 1 })

使用 hint() 方法的目的是强制 MongoDB 使用特定的索引,而不是执行计划所选择的默认索引。

3.3 covered query

covered query:是指 MongoDB 是从索引本身获取查询结果,而不是从文档中读取结果。

意义:

提高性能

减少磁盘 I/O

情况:

如果在查询中使用 covered query。返回结果的 projection (projection 是用于检索文档中某些字段的语句)不能包括任何字段(为空 projection {}),MongoDB 可以使用索引返回结果,并避免检查集合本身。

如果查询需要的数据不能全部使用索引获取,则需要检查其他列以完成查询。当出现这种情况时,指数只能回报索引行并不包含完整的映射行,并且将进行查询集合以获取所需的所有数据。

4. MongoDB 索引最佳实践

为了实现最佳的查询性能,下面的最佳实践对于数据访问和查询执行非常重要:

仅保存关键数据:在保留文档数据的同时,使用 $projection 过滤查询结果中不需要的数据。

针对经常执行的操作创建索引:注意对查询经常出现的字段进行索引。

选择最佳的索引类型:对不同类型的查询使用适当的索引。

删除不必要的索引:避免创建不必要的索引,因为它们可能浪费空间和 CPU 资源。

升级到最新版本的 MongoDB:每个新版本都有对索引的性能提升和更好的功能。

5. 总结

本文详细介绍了 MongoDB 索引的类型、使用方法和最佳实践。在实际应用中,需要根据业务特点和使用场景选择不同类型的索引,并对索引进行适当的维护和优化。

数据库标签