11

【赵强老师】MongoDB中的索引(上)

 3 years ago
source link: https://segmentfault.com/a/1190000038321079
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

U7FVnyU.jpg!mobile

索引是提高查询查询效率最有效的手段。索引是一种特殊的数据结构,索引以易于遍历的形式存储了数据的部分内容(如:一个特定的字段或一组字段值),索引会按一定规则对存储值进行排序,而且索引的存储位置在内存中,所在从索引中检索数据会非常快。如果没有索引,MongoDB必须扫描集合中的每一个文档,这种扫描的效率非常低,尤其是在数据量较大时。

一、索引的基础知识

下面以关系型数据库Oracle为例,介绍索引的基本原理,如下图所示:

UnuERri.png!mobile

从上图可以看成,索引的本质其实就相当于是一本书的目录。当查询表中数据的时候,先查询目录(索引)中的行地址,再通过行地址查询到表中的数据,从而提高查询的性能。

下图说明了在MongoDB中,索引在查询和排序中是如何工作的?

ayQJbyJ.png!mobile

通过这个例子,可以清楚的看到索引存储的是一个特定字段或者几个字段的集合,并且按照一定的规律排序。当创建集合的时候,MongoDB自动在\_id上创建一个唯一性索引,由于是唯一性的,所以可以防止重复的\_id值插入到集合中。通过getIndexes可以查询到MongoDB集合上的索引信息,如下图所示。

ErqQneq.png!mobile

当没有索引的时候,通过查看执行计划,可以看到查询的过程,如下:查询:10号部门,工资小于3000的文档。

EZRv2y.png!mobile

那么如何创建一个简单的索引呢?注意从mongoDB 3.0开始ensureIndex被废弃,今后都仅仅是db.collection.createIndex的一个别名。

MFN7Rz3.png!mobile

现在在deptno和sal上建立一个索引,并重新查看执行计划:db.emp.createIndex({"deptno":1,"sal":-1})

uMzINru.png!mobile

注意:除了可以使用explain()生成执行计划外,还可以有几个可选的参数,如下:

.explain("allPlansExecution")

.explain("executionStats")

.explain("queryPlanner")

二、索引的类型一:单键索引(Single Field)

单键索引是最普通的索引,与_id索引不同,单键索引不会自动创建。

准备数据:
db.testindex1.insert({"_id":1,"zipcode":1034,"location":{state:"NY",city:"New York"}})

在单个列上创建单键索引:
db.testindex1.createIndex({"zipcode":1})

在嵌套的列上创建单键索引
db.testindex1.createIndex({"location:state":1})

在内嵌的文档上创建单键索引
db.testindex1.createIndex({"location":-1})
这样将会把location作为一个整体。

三、索引的类型二:多键索引(Multikey Index)

多键索引与单键索引创建形式相同,区别在于字段的值。值具有多个记录,如数组。

Nn6nIvJ.png!mobile

如上图,基于集合上的数组创建多键索引,且数组为内嵌文档。

准备数据:
db.testindex2.insertMany([
{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] },
{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] },
{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] },
{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] },
{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }])

下面基于ratings列创建一个多键索引:
db.testindex2.createIndex( { ratings: 1 } )

查询数组上为5,9的文档
db.testindex2.find( { ratings: [ 5, 9 ] } )

下面查看其执行计划
db.testindex2.find( { ratings: [ 5, 9 ] } ).explain()

uE36Rnu.png!mobile

U7FVnyU.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK