索引通常能够极大的提高查询的效率, 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中。 MongoDB中使用 B树
数据结构存储索引。
如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。扫描全集合的查询效率是非常低的。
1、查看索引(1)查看集合中所有的索引
语法格式如下: db.COLLECTION_NAME.getIndexes()
> db.coll3.find()
{ "_id" : ObjectId("6084d6ecee8694c350d73907"), "name" : "赵云", "age" : 18, "sex" : 1 }
{ "_id" : ObjectId("6084d6ecee8694c350d73908"), "name" : "赵紫", "age" : 20, "sex" : 1 }
{ "_id" : ObjectId("6084d6ecee8694c350d73909"), "name" : "猴子", "age" : 21, "sex" : 1 }
{ "_id" : ObjectId("6084d6ecee8694c350d7390a"), "name" : "露娜", "age" : 17, "sex" : 0 }
{ "_id" : ObjectId("6084d6ecee8694c350d7390b"), "name" : "上官婉儿", "age" : 16, "sex" : 0 }
{ "_id" : ObjectId("6084d748ee8694c350d7390c"), "name" : "孙尚香", "age" : 19, "sex" : 1 }
> db.coll3.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "m_db1.coll3"
}
]
- _id 是默认的索引。
MongoDB在创建集合的过程中,在_id字段上创建一个唯一的索引,该索引不可以被删除。 索引名的默认的名称规则为: 字段名后面加_和排序(排序有的话)
。
(2)查看集合索引大小
语法格式如下: db.COLLECTION_NAME.totalIndexSize()
> db.coll3.totalIndexSize()
36864
2、创建索引
语法格式如下: db.COLLECTION_NAME.createIndex(keys, options)
- keys键值对:
格式:{字段: 1或-1}
,1表示在字段上的升序索引,-1则为降序索引 - options:可选参数,列表如下:
(1)单字段索引创建 给 age 字段创建降序索引,并起个索引名。
> db.coll3.createIndex({age: -1}, {name: "idx_age_-1"})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
(2)复合索引创建
> db.coll3.createIndex({_id:1, name:1}, {background: true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.coll3.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "m_db1.coll3"
},
{
"v" : 2,
"key" : {
"age" : -1
},
"name" : "idx_age_-1",
"ns" : "m_db1.coll3"
},
{
"v" : 2,
"key" : {
"_id" : 1,
"name" : 1
},
"name" : "_id_1_name_1",
"ns" : "m_db1.coll3",
"background" : true
}
]
3、删除索引
(1)删除集合中的指定索引
语法格式如下: db.COLLECTION_NAME.dropIndex(索引名称 或 索引键值对)
> db.coll3.dropIndex("idx_age_-1")
{ "nIndexesWas" : 3, "ok" : 1 }
> db.coll3.dropIndex({age: -1})
{
"ok" : 0,
"errmsg" : "can't find index with key: { age: -1.0 }",
"code" : 27,
"codeName" : "IndexNotFound"
}
(2)删除集合中所有索引
语法格式如下: db.COLLECTION_NAME.dropIndexes()
- 不会将_id索引删除,只能删除_id之外的索引
> db.coll3.dropIndexes()
{
"nIndexesWas" : 3,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
二、查询分析
创建几个索引,然后查询数据分析:
> db.coll3.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "m_db1.coll3"
},
{
"v" : 2,
"key" : {
"_id" : 1,
"name" : 1
},
"name" : "_id_1_name_1",
"ns" : "m_db1.coll3",
"background" : true
},
{
"v" : 2,
"key" : {
"age" : -1
},
"name" : "idx_age_-1",
"ns" : "m_db1.coll3"
}
]
MongoDB 查询分析常用函数有:explain() 和 hint()。 这里我们通过 explain()()
来查询分析创建的索引是否有效。 explain()
操作提供了查询信息、使用索引、查询统计等,有利于我们对索引的优化。
语法格式如下: db.COLLECTION_NAME.find().explain()
1.1 索引查询(1)使用age索引
> db.coll3.find({age: {$gt: 18}})
{ "_id" : ObjectId("6084d6ecee8694c350d73909"), "name" : "猴子", "age" : 21, "sex" : 1 }
{ "_id" : ObjectId("6084d6ecee8694c350d73908"), "name" : "赵紫", "age" : 20, "sex" : 1 }
{ "_id" : ObjectId("6084d748ee8694c350d7390c"), "name" : "孙尚香", "age" : 19, "sex" : 1 }
> db.coll3.find({age: {$gt: 18}}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "m_db1.coll3",
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$gt" : 18
}
},
"queryHash" : "4BB283C4",
"planCacheKey" : "DF7FEF1F",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : -1
},
"indexName" : "idx_age_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"age" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[inf.0, 18.0)"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "centos7",
"port" : 27017,
"version" : "4.2.13",
"gitVersion" : "82dd40f60c55dae12426c08fd7150d79a0e28e23"
},
"ok" : 1
}
常见参数说明:重点看 stage
和 indexOnly
,这两个字段有时候可能并不会存在。
- stage:当值为
COLLSCAN
时,表示全集合扫描,这样的性能是比较低的。当值为IXSCAN
时,是基于索引扫描,创建索引后我们需要保证查询是基于索引扫描的 - indexOnly: 字段为 true ,表示我们使用了索引。
- indexBounds:当前查询具体使用的索引。
通过图形化工具也可直观分析。再分析一个。
覆盖索引
:当查询条件和所要查询的列全部都在索引中时,而不需要回表查询记录。 MongoDB会直接从索引返回结果。这样的查询性能非常的高。
Stay Hungry, Stay Foolish. 求知若饥,虚心若愚。