美文网首页
Mongodb基础二:索引原理与使用

Mongodb基础二:索引原理与使用

作者: joyitsai | 来源:发表于2019-05-30 15:37 被阅读0次

1. 索引的原理?

索引是对数据库表中一列或多列的值进行排序的一种数据结构,可以让我们查询数据库变得更快。为了方便后续介绍,先科普下MongoDB里的索引机制(同样适用于其他的数据库比如mysql)。

> db.person.find()
{ "_id" : ObjectId("571b5da31b0d530a03b3ce82"), "name" : "jack", "age" : 19 }
{ "_id" : ObjectId("571b5dae1b0d530a03b3ce83"), "name" : "rose", "age" : 20 }
{ "_id" : ObjectId("571b5db81b0d530a03b3ce84"), "name" : "jack", "age" : 18 }
{ "_id" : ObjectId("571b5dc21b0d530a03b3ce85"), "name" : "tony", "age" : 21 }
{ "_id" : ObjectId("571b5dc21b0d530a03b3ce86"), "name" : "adam", "age" : 18 }

当你往某各个集合插入多个文档后,每个文档在经过底层的存储引擎持久化后,会有一个位置信息,通过这个位置信息,就能从存储引擎里读出该文档。为方便介绍,统一用pos(position的缩写)来代表位置信息。

比如上面的例子里,person集合里包含插入了5个文档,假设其存储后位置信息如下(为方便描述,文档省去_id字段)

位置信息 文档
pos1 {“name” : “jack”, “age” : 19 }
pos2 {“name” : “rose”, “age” : 20 }
pos3 {“name” : “jack”, “age” : 18 }
pos4 {“name” : “tony”, “age” : 21}
pos5 {“name” : “adam”, “age” : 18}

假设现在有个查询 db.person.find( {age: 18} ), 查询所有年龄为18岁的人,这时需要遍历所有的文档(全表扫描),根据位置信息读出文档,对比age字段是否为18。当然如果只有4个文档,全表扫描的开销并不大,但如果集合文档数量到百万、甚至千万上亿的时候,对集合进行全表扫描开销是非常大的,一个查询耗费数十秒甚至几分钟都有可能。

如果想加速 db.person.find( {age: 18} ),就可以考虑对person表的age字段建立索引

db.person.createIndex( {age: 1} )  // 按age字段创建升序索引

建立索引后,MongoDB会额外存储一份按age字段升序排序的索引数据,索引结构类似如下,索引通常采用类似btree的结构持久化存储,以保证从索引里快速(O(logN)的时间复杂度)找出某个age值对应的位置信息,然后根据位置信息就能读取出对应的文档。

AGE 位置信息
18 pos3
18 pos5
19 pos1
20 pos2
21 pos4

简单的说,索引就是将文档按照某个(或某些)字段顺序组织起来,以便能根据该字段高效的查询。

众所周知,MongoDB默认会为插入的文档生成_id字段(如果应用本身没有指定该字段),_id是文档唯一的标识,为了保证能根据文档id快递查询文档,MongoDB默认会为集合创建_id字段的索引。

> db.person.getIndexes() // 查询集合的索引信息
[
    {
        "ns" : "test.person",  // 集合名
        "v" : 1,               // 索引版本
        "key" : {              // 索引的字段及排序方向
            "_id" : 1           // 根据_id字段升序索引
        },
        "name" : "_id_"        // 索引的名称
    }
]

2. MongoDB索引的基本使用

2.1 单字段索引
  • 创建单字段索引:
> db.user.ensureIndex({name: 1})

上述语句针对name创建了单字段索引,其能加速对name字段的各种查询请求,是最常见的索引形式,MongoDB默认创建的id索引也是这种类型。

{name: 1}代表升序索引,也可以通过{name: -1}来指定降序索引,对于单字段索引,升序/降序效果是一样的。

  • 查看当前集合的所有索引信息:
> db.user.getIndexes()
  • 删除单字段索引:
db.user.dropIndex({name: 1});
2.2 复合索引:

数字1表示name键的索引按升序存储,-1表示age键的索引按照降序方式存储。

db.user.ensureIndex({"name":1, "age":-1})

该索引被创建后,基于nameage的查询将会用到该索引,或者是基于name的查询也会用到该索引,但是只基于age的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列

如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用。如:

 db.user.find({"age": 30, "name": "stephen"})

对于上面示例中的查询条件,MongoDB在检索之前将会动态的调整查询条件的顺序,以使该查询可以用到刚刚创建的复合索引。

对于上面创建的索引,MongoDB都会根据索引的keyname和索引方向为新创建的索引自动分配一个索引名,下面的命令可以在创建索引时为其指定索引名(userindex),如:

db.user.ensureIndex({"name":1},{"name":"userindex"})

2.3 唯一索引

在缺省{unique:true}的情况下创建的索引均不是唯一索引。下面将创建唯一索引,如:

 db.user.ensureIndex({"userid":1},{"unique":true})

如果再次插入userid重复的文档时,MongoDB将报错,以提示插入重复键,如:

db.user.insert({"userid":5}) 
db.user.insert({"userid":5})

E11000 duplicate key error index: user.user.$userid_1 dup key: { : 5.0 }

如果插入的文档中不包含userid键,那么该文档中该键的值为null,如果多次插入类似的文档,MongoDB将会报出同样的错误:
E11000 duplicate key error index: user.user.$userid_1 dup key: { : null }

3. 使用explain

explain是非常有用的工具,会帮助你获得查询方面诸多有用的信息:
explain会返回查询使用的索引情况,耗时和扫描文档数的统计信息。

3.1 explain( 'executionStats' )查询具体的执行时间
db.tablename.find().explain( "executionStats" )

输出的如下数值:explain.executionStats.executionTimeMillis就是当前数据查询所用的时间。

参考《MongoDB索引原理》

相关文章

  • Mongodb基础二:索引原理与使用

    1. 索引的原理? 索引是对数据库表中一列或多列的值进行排序的一种数据结构,可以让我们查询数据库变得更快。为了方便...

  • mongodb学习2

    MongoDB 索引 和 explain 的使用 索引基础唯一索引索引的一些参数使用 explainexplain...

  • MongoDb学习总结

    大纲: 1、MongoDB的体系结构2、MongoDB安装配置与基础命令3、MongoDB CRUD与全文索引4、...

  • MongoDB索引二(九)

    MongoDB索引二(九) 接上篇MongoDB索引一

  • MySQL,必须掌握的6个知识点

    目录 一、索引B+ Tree 原理 MySQL 索引 索引优化 索引的优点 索引的使用条件 二、查询性能优化使用 ...

  • 4.5MongoDB实现地理位置索引

    MongoDB支持二维空间索引,使用空间索引,mongoDB支持一种特殊查询,如某地图网站上可以查找离你最近的咖啡...

  • mongo的索引

    MongoDB 索引 createIndex() 方法 MongoDB使用 createIndex() 方法来创建...

  • mongoDB 数据重复问题

    MongoDB 索引 createIndex() 方法MongoDB使用 createIndex() 方法来创建索...

  • mongoDB基本, 2022-08-26

    (2022.08.26 Thur) 本文包括 mongoDB的应用场景 数据架构 高可用与高扩展 基础语法、索引 ...

  • Elasticsearch 调研

    1. 基础概念 1.1 倒排索引原理 1.2 倒排索引构成 单词词典,使用 BTree 记录所有文档的单词,记录单...

网友评论

      本文标题:Mongodb基础二:索引原理与使用

      本文链接:https://www.haomeiwen.com/subject/lboytctx.html