MongoDB 索引

说明:本篇文章介绍常用的索引创建的方式与删除,另外介绍 过期索引的使用,以及查询分析(explain 函数的使用)

MongoDB 索引

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

MongoDB 的索引算法主要是使用 btree 与 hash 算法。默认是使用 btree。

MongoDB 两种创建索引的方式

自动创建

    当我们在 MongoDB 的集合中插入数据之后,会自动创建一个 "_id" 的 key值,这个 key 上面就会有 MongoDB 自动创建的索引在。

手动创建

    我们使用 createIndex() 语法创建索引。在 3.0.0 版本之前,是使用 ensureIndex() 创建索引。

语法

db.collection.createIndex(keys, options)

参数说明:

  • key:创建索引的字段, 1 为升序创建索引,-1 为降序创建索引。
  • options:传入不同的参数,用于生成不同的索引(比如唯一索引,哈希索引),以及在后台运行

索引的分类

普通索引 ({field:1/-1})
唯一索引 ({filed.subfield:1/-1}, {unique:true})
稀疏索引 ({field:1/-1},{sparse:true})
哈希索引 ({file:'hashed'})

说明

稀疏索引的特点:如果针对field做索引,针对不含field列的文档,将不建立索引。与之相对,普通索引,会把该文档的field列的值认为NULL,并建索引。应用场景:小部分文档含有某列时。

哈希索引速度比普通索引快,但是,无法对范围查询进行优化。适宜于:随机性强的散列。

使用

// 以 title 字段创建升序索引
db.collection.createIndex({"title":1})

// 使用多个字段创建索引
db.collection.createIndex({"title":1, "name": 1})

// 创建唯一索引
db.collection.createIndex({"name" : 1}, {unique:true})

// 后台创建索引
db.collection.createIndex({"title" : 1, "name": 1}, {background: true})

// 查看集合索引
db.collection.getIndexes()

// 查看集合索引大小
db.collection.totalIndexSize()

// 创建子文档索引
db.collection.createIndex({filed.subfield:1/-1});
// 例如
db.collection.createIndex({"product.price":1});

// 创建哈希索引
db.collection.createIndex({"name" : 'hash'});

部分操作截图:

过期索引

过期索引:是指在一段时间过后会过期的索引(感觉像是废话)。重点是在索引过期之后,相应的数据会被删掉。这样式适合存储一些在一段时间需要丢弃掉的数据。

需要说明的是:这个过期索引的时间并不是特别准时。比如设置的是 10s,但是 10s 之后并不一定会删除。可能需要等待的时间更加长一些。

 

建立过期索引

// field 必须是日期格式字段
db.collection.createIndex({filed : 1/-1}, {expireAfterSeconds: 秒为单位的数值 });

示例:给集合中的 name 字段加上 过期索引,30秒之后过期。

db.collection.createIndex({"date": 1}, {"expireAfterSeconds" : 30})

过期索引特别说明

  1. 存储在过期索引字段的值必须是指定的时间类型(ISODate 或者 ISODate 数组)
  2.  如果指定了ISODate()数组,则按照最小的时间进行删除。
  3.  过期索引不能是复合索引,因为我们不能指定两个过期时间索引。
  4. 删除过程是由后台程序每60s跑一次,而且删除也需要一些时间,索引存在误差

删除索引

示例:删除所有索引(只能删除非 "_id" 的索引)

db.collection.dropIndexes()

示例:删除集合指定的索引

db.collection.dropIndex({filed : 1/-1}) 
// 例如 
db.collection.dropIndex({"title" : 1 });

使用 explain() 分析

使用 explain() 函数分析查询。

# 语法 
db.collection.find().explain();

没有创建索引的扫描

图示中使用的是全集合扫描(没有创建索引):

创建索引并且扫描

创建索引之后分析如下:

// 添加索引
 db.products.createIndex({"sku":1});

// 输出结果
    {
       "createdCollectionAutomatically" : false,
       "numIndexesBefore" : 1,
       "numIndexesAfter" : 2,
       "ok" : 1
    }

// 执行查询分析
 db.products.find({"sku":"abc123"}).explain();

// 输出结果
      {"queryPlanner" : {
               "plannerVersion" : 1,
               "namespace" : "study.products",
               "indexFilterSet" : false,
               "parsedQuery" : {
                       "sku" : {
                               "$eq" : "abc123"
                       }
               },
               "winningPlan" : {
                       "stage" : "FETCH",
                       "inputStage" : {
                               "stage" : "IXSCAN",
                               "keyPattern" : {
                                       "sku" : 1
                               },
                               "indexName" : "sku_1",
                               "isMultiKey" : false,
                               "isUnique" : false,
                               "isSparse" : false,
                               "isPartial" : false,
                               "indexVersion" : 1,
                               "direction" : "forward",
                               "indexBounds" : {
                                       "sku" : [
                                               "[\"abc123\", \"abc123\"]"
                                       ]
                               }
                       }
               },
               "rejectedPlans" : [ ]
       },
       "serverInfo" : {
               "host" : "GZ-YY-WQ",
               "port" : 27017,
               "version" : "3.2.6",
               "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25"
       },
       "ok" : 1
       }

当我们使用两个字段作为查询条件时,其中一个字段没有索引,另一个有索引,使用 explain() 函数执行结果显示也是 全集合查询。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值