前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有

我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有

作者头像
小小许
发布于 2020-12-16 07:23:00
发布于 2020-12-16 07:23:00
1K00
代码可运行
举报
文章被收录于专栏:angularejs学习篇angularejs学习篇
运行总次数:0
代码可运行

这是mongo第四篇“索引探索”,后续会连续更新4篇

  mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流。通过上三篇的介绍,我相信大家对我在使用上已经很溜啦,但是在实际使用中还需要注重效率提升,本文章探索索引,就是为提升效率为出发点,本文的介绍顺序是:索引简介->索引原理->索引类型->索引与查询结合使用->小结,让我们一起来一步一步的探索吧。​

01

索引简介

  Mongodb的索引和其它关系型数据库索引很类似,索引是一个存储结构,其存储的内容是数据文档持久化的位置信息。一个数据集合和一本书来对比,那么索引就是书对应的目录,其作用就是加快查询效率。索引在加快查询效率的同时,在更新、删除、新增数据时也会影响数据变更效率,因为每一次数据变更都会更新一次索引。所以在索引使用时也需要慎重。

Mongodb索引的基本命令包括:

新增索引:createIndex({字段:排序方式},{可选参数})

删除索引:dropIndex({字段:排序方式})

查看索引:getIndexes()

先不管索引为什么能够提高查询效率,降低数据变更效率,先来一个实例。为了体现效果,这次我整的有点狠,直接初始化了300多万条数据,演示步骤如下:

数据初始化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for(var i=0;i<3000000 ;i++)

{
     db.user.insert({
        name:"我叫"+i,
        age:i%10,  
        from:i%10000
   })
}        

  // 上面的数据有一个特点age的值就10个,from的值有10000个。下面分别对两个字段加上索引,并通过实际的执行语句来看效果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
给user表的age添加一个索引(age升序)

db.user.createIndex({age:1})

给user表的from添加一个索引(from升序)

db.user.createIndex({from:1})

  其实我们都知道索引能够提高查询效率,估计很少亲自测试一把,通过测试是不是有一种爽歪歪的感觉。根据实际操作结果我们先得出几点小小的结论:

  • 当字段的值是有限的一些值时,其实有无索引对效率无影响;
  • 当字段的值重复数据少时,索引的查询效率明显提高几百倍;
  • 当查询结果需要排序时,有索引比没索引的效率高50倍左右;
  • 当更新时,有索引的效率低于无索引;
  • 所以在添加索引时针对字段值是有限的值时,就没必要添加索引,当经常需要用于排序的字段可以考虑添加索引。

  以上的几个结论,也是我通过实际数据操作得出的,如果有不准确的地方,希望指点改正,谢谢!

  先把结论得到这儿,下面我们在一步一步的剖析索引。

02

索引原理

  Mongdb数据通过存储引擎持久化以后,其实在磁盘中就是一个一个的文件,每一个文件都对应一个位置信息。索引就是这一些文件位置信息与索引字段值的对应关系的有序数据集合,索引采用btree的结构持久化存储。在创建索引后,数据在查询的时,直接索引数据集合查询,然后在根据对于的位置信息操作对应的数据详情,避免了全表扫描,同时查询出的数据本来就是有序的数据,也避免了因为排序导致的性能损失。

  这样我们就不难理解上面得出的几点结论了:因为索引查询避免了全表数据扫描,所有查询效率高;因为索引本身就已经是有序的数据,所以根据索引字段排序效率明显提高;因为索引会单击存储,一旦数据有变更,都需要同时更新索引数据,所有数据更新时有索引的效率低,同时索引也会增加额外的存储开销。

03

索引类型

  MongoDB支持多种类型的索引,包括单字段索引、复合索引、多key索引、文本索引等,每种类型的索引有不同的使用场合。

  单字段索引:

  单字段索引其实很好理解,文章开始我们创建的实例就是单字段索引,简单的所说就是针对某一个字段创建一个索引,达到提高索引字段的查询效率。Mongdb默认_id字段创建单字段唯一索引。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 格式:db.collectionName.createIndex({索引字段:1升序-1降序} )

  实例:对集合user的字段age添加升序索引

  db.user.createIndex({age:1})

  复合索引:

  复合索引是针对单字段索引的升级版,复合索引就是联合多个字段创建索引,也是我们常说的联合索引。复合索引在数据存储上,首先根据第一字段排序、然后当第一字段值相同时在以第二字段排序、依次类推第N字段。复合索引能够满足以下两个场景的查询需要:根据复合索引多个字段组合查询;根据所有前缀字段查询,也就是所有字段的顺序的第一个至第N个的前缀字段查询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
格式:db.collectionName.createIndex({索引字段1:排序, 索引字段2:排序} )

实例:对集合user添加字段from降序、age升序索引

db.user.createIndex({from:-1,age:1 })

以下情况可以使用到索引:

db.user.find({from:20,age:8})、db.user.find({from:20})

以下情况不能使用索引:

db.user.find({age:8,from:20})、db.user.find({age:8})

  根据复合索引的使用情况得出以下几点小结论:

  • 索引使用顺序一定要和索引创建顺序保持一致;
  • 当索引字段不完全组合查询时,需要前序字段连续;
  • 创建索引时最好取值丰富的字段在前。

  多key索引:

  多key索引是指创建的索引字段为数组,多key索引会为数组的每个元素建立一条索引,使用场景就是针对字段值是数组的查询。有了前面的基础,这一个就很好理解,就不在详细描述了。

  文本索引:

  文本索引,简单的说就是针对文本数据创建索引,比如,文章信息表,如果需要根据文章关键词检索,那么就可以对文章字段创建文本索引。格式为:db.collectionName.createIndex({索引字段1: "text" } )

04

索引额外属性说明

  createIndex创建索引时,该方法有两个参数,第一个参数就是索引字段,上面已经说了,第二个参数就是索引的额外属性,下面我们就说说索引额外属性信息。索引额外属性包括:唯一索引、TTL索引、稀疏索引。

  TTL索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  TTL索引属性是修饰当文档存储自定时间,当超出指定时间后,数据被被自动删除,使用场景为数据只存储指定时间,如:日志数据,关键词为expireAfterSecs,格式为:db.collectionName.createIndex({索引字段1: "text" }, {"expireAfterSecs": 失效时间单位为秒})

TTL索引几点注意事项:

  • TTL只使用于时间字段
  • TTL不使用于联合索引
  • TTL如果对于索引值是数组,那么只要其中一个值满足要求就自动删除

  唯一索引 (unique index):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 保证索引对应的字段不会出现相同的值,比如_id索引就是唯一索引。格式为:db.collectionName.createIndex({索引字段1: "text" }, {"unique": true})
代码语言:javascript
代码运行次数:0
运行
复制

  部分索引 (partial index):

只针对符合某个特定条件的文档建立索引,3.2版本才支持该特性。关键词为partialFilterExpression

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 格式为:db.collectionName.createIndex({索引字段1: "text" }, {"partialFilterExpression": {数据满足条件表达式}})。

  比如:对表user只有age=9的数据创建索引

  db.user.createIndex({age:1},

  {"partialFilterExpression":{age:9}})

  稀疏索引(sparse index):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  只针对存在索引字段的文档建立索引,可看做是部分索引的一种特殊情况。关键词为:sparse,格式为:db.collectionName.createIndex({索引字段1: "text" }, {"sparse": true})
代码语言:javascript
代码运行次数:0
运行
复制

06

索引优化(profiling)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 其实我们在建集合的时候,很多时候最开始是不知道那一些字段需要添加索引,是需要根据后续的实际使用场景来动态创建,那么这就会有一个问题,如果监控哪一些字段需要添加或是删除索引,可通过检测每一次操作结果的响应时间长短来动态创建索引,mongdb提供了一个profiling来动态检测执行响应情况。

MongoDB支持对DB的请求进行profiling,目前支持3种级别的profiling。

  • 0: 不开启profiling
  • 1: 将处理时间超过某个阈值(默认100ms)的请求都记录到DB下的system.profile集合 (类似于mysql、redis的slowlog)
  • 2: 将所有的请求都记录到DB下的system.profile集合(生产环境慎用)

  通常,生产环境建议使用1级别的profiling,并根据自身需求配置合理的阈值,用于监测慢请求的情况,并及时的做索引优化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
开启profiling命令:db.setProfilingLevel(1,120 );
查询profil记录信息:db.system.profile.find()

   最终通过查询出来的记录信息,对索引进行优化。

07

小结

Mongdb在提升查询效率上是很有帮助,但是在实际使用中也不要滥用,否则会适得其反,下面总结几点,供参考:

    • 索引创建时最好作用于取值丰富的字段,有限值的字段就没必要添加索引;
    • 经常排序的字段,可以考虑添加索引;
    • 一个集合中索引的个数不是越多越好,需要根据实际情况来定;
    • 执行接口慢,有可能是缺少索引(查询慢),也有可能是索引使用不当(编辑慢);
    • 复合索引在使用时,一定要结合索引字段的顺序使用。
  • END 原创不易,感谢扫描支持,获取更多精彩,谢谢:
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
我叫Mongo,干了「查询终结篇」,值得您拥有
  mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流。
小小许
2020/11/11
1.4K0
mongodb必会知识点
8.2 架构 在数据承载节点中,一个且只有一个成员被视为主节点,而其他节点则被视为辅助节点。节点接收所有 写入操作,一个副本集只能有一个主实例能够写入,主节点记录所有变更到它的记录 辅助节点复制主节点的 oplog 并将操作应用于数据集。 仲裁员不维护数据集,仲裁器的目的是通过响应其 他副本集成员的心跳和选择请求来维护副本集中的仲裁。 因为它们不存储数据集,所以仲裁器是提供副本集仲裁功能的一种好方法。 与具有数据集的完全功能副本集成员相比,仲裁器的资源成本更低,如果副本集的成员数为偶数,则添 加一个仲裁器以在初选中获得多数票。 当一个主服务器在超过配置的周期(默认为 10 秒)内未与该组的其他成员通信时,符合条件的辅助服 务器将要求选择将其自身指定为新的主服务器。集群试图完成新的初选并恢复正常操作。 8.3 搭建步骤 (1) 准备三台虚拟机服务器,并各自安装好 mongoDB 注:为了保证复制集中三个服务器之间正常连接,请保证三个服务器的防火墙都已关闭! 192.168.132:27017 192.168.133:27017 192.168.134:27017 (2) 修改 mongodb.conf 文件,添加 replSet 配置 ( 三台都需要修改成同一个名称 ) ,然后启动服务器 replSet=rep1 (3) 初始化复制集 登录任意一台执行初始化操作 说明 : _id 指复制集名称, members 指复制集服务器列表,数组中的 _id 是服务器唯一的 id,host 服务器主 机 ip # 复制集名称 rs.initiate({_id:'rep1',members:[{_id:1,host:'192.168.197.132:27017'}, {_id:2,host:'192.168.197.133:27017'},{_id:3,host:'192.168.197.134:27017'}]}) (4) 查看集群状态 (5) 测试 # 添加数据 db.users.insert({"name":"lisi","age":11}) # 查询数据 db.users.find() # 切换到从数据库查询数据 如果不允许查询,是因为默认情况下从数据库是不允许读写操作的,需要设置。 >rs.slaveOK() 执行该命令后可以查询数据 (6) 测试复制集主从节点故障转移功能 # 关闭主数据库 , 注意从数据库的变 >db.shutdownServer() (7) 主复制集添加仲裁者 (arbiter) 现在我们的环境是一主两从,仲裁者对偶数集群有效。需要停止一个从机,在主服务器中运行下面命令 在一主一从关系中,任意节点宕机都无法选举出主节点,无法提供写操作,此时需要加入仲裁者节点即 可。 rs.remove("ip: 端口号 ") // 删除从节点 在一主一从关系中,任意节点宕机都无法选举出主节点,无法提供写操作,此时需要加入仲裁者节点即 可。 rs.addArb("ip: 端口号 ")
编程张无忌
2021/01/26
1.5K0
mongodb必会知识点
MongoDB(五)—-MongoDB中的索引类型
在MongoDB中支持多种类型的索引,包括单字段索引、复合索引、多key索引、文本索引等,每种类型的索引有不同的使用场合。
全栈程序员站长
2021/04/07
2.1K0
MongoDB入门(特点,使用场景,命令行操作,SpringData-MongoDB)
今天我们将通过这一篇博客来了解MongoDB的体系结构,命令行操作和在JAVA 当中使用SpringData-MongoDB 来 操作MongoDB。
叫我阿杰好了
2023/02/02
1.3K1
MongoDB入门(特点,使用场景,命令行操作,SpringData-MongoDB)
MongoDB 索引
当往一个集合中插入多个文档后,每个文档经过存储殷引擎后,有一个位置信息,通过这个位置信息。就能从存储引擎中读出该文档。在 mmapv1 引擎下,位置信息是【文件id+文件内 offset】 。在wiredtiger存储引擎里,位置信息是 wiredgiter 在存储文档时生成的一个 key ,通过这个key 能访问到对应的文档。
王小明_HIT
2019/08/13
7610
MongoDB入门实战教程(9)
前面我们学习了如何套用常见的设计模式打造合适的模型设计,本篇我们来看看在MongoDB中如何使用索引来提高查询效率。
Edison Zhou
2021/07/01
1.7K0
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 聚合)--学习笔记
索引基数:数据类型多,索引基数高,索引效率高,如果数据比如性别只有男,女两种数据,索引效率低
郑子铭
2021/01/04
3920
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 聚合)--学习笔记
MongoDB初级入门
{ "_id" : "Mary", "sum_age" : 75 } { "_id" : "Jack", "sum_age" : 66 } { "_id" : "zhengyunamei", "sum_age" : 0 } { "_id" : "Tom", "sum_age" : 120 } { "_id" : "陈加兵", "sum_age" : 22 } { "_id" : "Lucy", "sum_age" : 66 } { "_id" : "郑元梅", "sum_age" : 22 }
爱撒谎的男孩
2018/06/07
1.4K0
MongoDB索引
创建索引的api,3.0之后使用createIndex,ensureIndex已经废弃 * 对于单字段索引,排序的顺序是升序还是降序无关紧要
字母哥博客
2020/09/23
1.6K0
mongodb 索引详解(二)
MongoDB为文档集合中的任何字段提供完整的索引支持 。默认情况下,所有集合在_id字段上都有索引,应用程序和用户可以添加其他索引以支持重要的查询和操作。
MongoDB中文社区
2019/07/08
1.3K0
mongodb如何添加索引
MongoDB是一个开源的文档数据库,采用分布式文件存储的方法,是NoSQL数据库中的一种。它的设计目标是为了在现代应用开发中解决传统关系型数据库所遇到的一些挑战,比如灵活性、可扩展性和性能等方面的问题。
半月无霜
2025/02/25
2300
MongoDB数据模型设计和索引创建
在MongoDB中,数据模型是非常重要的,它可以直接影响到数据库的性能和可扩展性。在本文中,我们将介绍如何设计MongoDB数据模型,并创建索引来提高查询效率。
玖叁叁
2023/04/13
2.4K0
MongoDB 的安装和基本操作
示例:db.User.update({name:"lucy"}, {$set:{age:100, sex:0}})
用户7630333
2023/12/07
3770
MongoDB 的安装和基本操作
MongoDB入门(三)
指定删除Array中的某一个元素,只要满足条件,就会将Array中所有满足条件的数据全部清除掉
传说之下的花儿
2023/11/25
2820
MongoDB入门(三)
MongoDB 常用操作笔记 find ,count, 大于小于不等, select distinct, groupby,索引
本博客将列举一些常用的MongoDB操作,方便平时使用时快速查询,如find, count, 大于小于不等, select distinct, groupby等
大鹅
2021/06/16
4.2K0
MongoDB 索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
拓荒者
2019/09/11
6520
mongodb创建索引和删除索引和背景索引background
MongoDB的背景索引允许在后台创建和重建索引,而不会对数据库的正常操作产生影响。背景索引的创建过程是非阻塞的,可以在业务运行时创建或重建索引,而不会中断其他操作。这使得我们可以在生产环境中安全地创建和维护索引,而不必担心对数据库性能造成负面影响。
oktokeep
2024/10/09
5600
【Rochester】MongoDB的基本语法和使用
注:MongDB中默认的数据库为test,如果你没有选择数据库,集合将默认存放在test数据库中
Rochester
2021/06/23
2.8K0
MongoDB 索引-Index
索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
用户9615083
2022/12/25
1.6K0
MongoDB 索引-Index
MongoDB(六)—-MongoDB索引的额外属性
唯一索引会保证索引对应的键不会出现相同的值,比如_id索引就是唯一索引 创建索引时也需要保证属性中内容是不重复的 语法格式:
全栈程序员站长
2021/04/07
1K0
相关推荐
我叫Mongo,干了「查询终结篇」,值得您拥有
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验