一、索引
索引通常能够极大的提高查询的效率,
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中。
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:可选参数,列表如下:
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
(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()
操作提供了查询信息、使用索引、查询统计等,有利于我们对索引的优化。
1、使用 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:当前查询具体使用的索引。
通过图形化工具也可直观分析。再分析一个。
1.2 覆盖索引查询
覆盖索引
:当查询条件和所要查询的列全部都在索引中时,而不需要回表查询记录。
MongoDB会直接从索引返回结果。这样的查询性能非常的高。
Stay Hungry, Stay Foolish. 求知若饥,虚心若愚。