1 mongoDB索引的管理

本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性。我们先简单了解一下索引:索引的本质就是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据(数据row或者document)的物理地址,索引可以大大加快查询的速度,这是因为使用索引后可以不再扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址(多数为B-tree查找),然后通过地址来访问相应的数据。

索引可以加快数据检索、排序、分组的速度,减少磁盘I/O,但是索引也不是越多越好,因为索引本身也是数据表,需要占用存储空间,同时索引需要数据库进行维护,当我们对索引列的值进行增改删操作时,数据库需要更新索引表,这会增加数据库的压力。

我们要根据实际情况来判断哪些列适合添加索引,哪些列不适合添加索引,一般遵循的规律如下:

主/外键列,主键用于强制该列的唯一性和组织表中数据的排列结构;外键可以加快连接的速度;

经常用于比较的类(大于小于等于等),因为索引已经排序,值就是大于/小于的分界点;

经常进行范围搜索,因为索引已经排序,其指定的范围是连续的;

经常进行排序的列,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

经常进行分组的列,因为索引已经排序,同一个值的所有数据地址会聚集在一块,很方便分组。

我们看一下mongoDB的索引使用,首先准备数据:

db.userinfos.insertMany([

{_id:1, name: "张三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen"]},

{_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip"]},

{_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip"]},

{_id:4, name: "赵六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] },

{_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京'},

{_id:6, name: "周八", age: 28,roles:["gen"], address:'上海'}

]);

索引的增删改查还是十分简单的,我们看一下索引管理的几个方法:

//创建索引,值1表示正序排序,-1表示倒序排序db.userinfos.createIndex({age:-1})//查看userinfos中的所有索引

db.userinfos.getIndexes()//删除特定一个索引

db.userinfos.dropIndex({name:1,age:-1})//删除所有的索引(主键索引_id不会被删除)

db.userinfos.dropIndexes()//如果我们要修改一个索引的话,可以先删除索引然后在重新添加。

2 mongoDB中常用的索引类型

1 单键索引

单键索引(Single Field Indexes)顾名思义就是单个字段作为索引列,mongoDB的所有collection默认都有一个单键索引_id,我们也可以对一些经常作为过滤条件的字段设置索引,如给age字段添加一个索引,语法十分简单:

//给age字段添加升序索引

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

其中{age:1}中的1表示升序,如果想设置倒序索引的话使用 db.userinfos.createIndex({age:-1}) 即可。我们通过explain()方法查看查询计划,如下图,看到查询age=23的document时使用了索引,如果没有使用索引的话stage=COLLSCAN。

因为document的存储是bson格式的,我们也可以给内置对象的字段添加索引,或者将整个内置对象作为一个索引,语法如下:

//1.内嵌对象的某一字段作为索引//在ename.firstname字段上添加索引

db.userinfos.createIndex({"ename.firstname":1})//使用ename.firstname字段的索引查询

db.userinfos.find({"ename.firstname":"san"})//2.整个内嵌对象作为索引//给整个ename字段添加索引

db.userinfos.dropIndexes()//使用ename字段的索引查询

db.userinfos.createIndex({"ename":1})

2 复合索引

复合索引(Compound Indexes)指一个索引包含多个字段,用法和单键索引基本一致。使用复合索引时要注意字段的顺序,如下添加一个name和age的复合索引,name正序,age倒序,document首先按照name正序排序,然后name相同的document按age进行倒序排序。mongoDB中一个复合索引最多可以包含32个字段。

//添加复合索引,name正序,age倒序

db.userinfos.createIndex({"name":1,"age":-1})//过滤条件为name,或包含name的查询会使用索引(索引的第一个字段)

db.userinfos.find({name:'张三'}).explain()

db.userinfos.find({name:"张三",level:10}).explain()

db.userinfos.find({name:"张三",age:23}).explain()//查询条件为age时,不会使用上边创建的索引,而是使用的全表扫描

db.userinfos.find({age:23}).explain()

执行查询时查询计划如下:

3 多键索引

多键索引(mutiKey Indexes)是建在数组上的索引,在mongoDB的document中,有些字段的值为数组,多键索引就是为了提高查询这些数组的效率。看一个栗子:准备测试数据,classes集合中添加两个班级,每个班级都有一个students数组,如下:

db.classes.insertMany([

{"classname":"class1","students":[{name:'jack',age:20},

{name:'tom',age:22},

{name:'lilei',age:25}]

},

{"classname":"class2","students":[{name:'lucy',age:20},

{name:'jim',age:23},

{name:'jarry',age:26}]

}]

)

为了提高查询students的效率,我们使用 db.classes.createIndex({'students.age':1}) 给students的age字段添加索引,然后使用索引,如下图:

4 哈希索引

哈希索引(hashed Indexes)就是将field的值进行hash计算后作为索引,其强大之处在于实现O(1)查找,当然用哈希索引最主要的功能也就是实现定值查找,对于经常需要排序或查询范围查询的集合不要使用哈希索引。

3 mongoDB中常用的索引属性

1  唯一索引

唯一索引(unique indexes)用于为collection添加唯一约束,即强制要求collection中的索引字段没有重复值。添加唯一索引的语法:

//在userinfos的name字段添加唯一索引

db.userinfos.createIndex({name:1},{unique:true})

看一个使用唯一索引的栗子:

2  局部索引

局部索引(Partial Indexes)顾名思义,只对collection的一部分添加索引。创建索引的时候,根据过滤条件判断是否对document添加索引,对于没有添加索引的文档查找时采用的全表扫描,对添加了索引的文档查找时使用索引。使用方法也比较简单:

//userinfos集合中age>25的部分添加age字段索引

db.userinfos.createIndex(

{age:1},

{ partialFilterExpression: {age:{$gt:25}}}

)//查询age<25的document时,因为age<25的部分没有索引,会全表扫描查找(stage:COLLSCAN)

db.userinfos.find({age:23})//查询age>25的document时,因为age>25的部分创建了索引,会使用索引进行查找(stage:IXSCAN)

db.userinfos.find({age:26})

当查询age=23的记录时,stage=COLLSCAN,当查询age=26的记录时,使用了索引,如下:

2 稀疏索引

稀疏索引(sparse indexes)在有索引字段的document上添加索引,如在address字段上添加稀疏索引时,只有document有address字段时才会添加索引。而普通索引则是为所有的document添加索引,使用普通索引时如果document没有索引字段的话,设置索引字段的值为null。

稀疏索引的创建方式如下,当document包含address字段时才会创建索引:

//创建在address上创建稀疏索引

db.userinfos.createIndex({address:1},{sparse:true})

看一个使用稀疏索引的栗子:

4 TTL索引

TTL索引(TTL indexes)是一种特殊的单键索引,用于设置document的过期时间,mongoDB会在document过期后将其删除,TTL非常容易实现类似缓存过期策略的功能。我们看一个使用TTL索引的栗子:

//添加测试数据

db.logs.insertMany([

{_id:1,createtime:new Date(),msg:"log1"},

{_id:2,createtime:new Date(),msg:"log2"},

{_id:3,createtime:new Date(),msg:"log3"},

{_id:4,createtime:new Date(),msg:"log4"}

])//在createtime字段添加TTL索引,过期时间是120s

db.logs.createIndex({createtime:1}, { expireAfterSeconds: 120})//logs中的document在创建后的120s后过期,会被mongoDB自动删除

注意:TTL索引只能设置在date类型字段(或者包含date类型的数组)上,过期时间为字段值+exprireAfterSeconds;document过期时不一定就会被立即删除,因为mongoDB执行删除任务的时间间隔是60s;capped Collection不能设置TTL索引,因为mongoDB不能主动删除capped Collection中的document。

小结

本节介绍了mongoDB中常用的索引和索引属性,索引对提升数据检索的速度十分重要,在数据量比较大的时候一般都要在collection上建立索引。mongoDB提供的索引种类很丰富,总会有几种适用于我们的业务,除了上边介绍的索引外,mongoDB还支持text index和一些地理位置相关的索引,这里不再介绍,有兴趣的小伙伴可以到官网 研究下。如果文中有错误的话,希望大家可以指出,我会及时修改,谢谢。

mongo 唯一约束索引_快速掌握mongoDB(三)——mongoDB的索引详解相关推荐

  1. mysql 强制使用索引_快速找出MySQL数据库冗余索引和未使用索引

    冗余索引和未使用索引的危害 随着上线的业务越来越多,在MySQL数据库中建的表也会越来越多,为提高查询访问速度,会创建相应的索引.但是由于技术人员的水平参差不齐,业务下线,代码逻辑变更等原因,导致线上 ...

  2. C++框架_之Qt的信号和槽的详解

    目录 C++_之Qt的信号和槽的详解 1.概述 1.1对象树(子对象动态分配空间不需要释放) 2.信号和槽 Qt5 的书写方式:(推荐的使用)★★★★★ Qt4 的书写方式: 3.自定义信号槽 3.1 ...

  3. 计算机主板一直滴滴响,主板报警声大全_主板一直滴滴滴短响含义详解

    主板报警声大全_主板一直滴滴滴短响含义详解 在电脑使用过程中,有时我们会听到电脑主板发出类似报警的声音,这时候说明可能电脑主板出现了一定的问题,电脑主板报警的原因有很多,我们可以从报警的声音去区分到底 ...

  4. mongo 唯一约束索引_Java:MySQL 基础知识+索引相关

    阅读本文前,请您先点击上面的蓝色字体,再点击"关注",这样您就可以继续免费收到最新文章了.每天都有分享.完全是免费订阅,请放心关注.注:本文转载自网络,不代表本平台立场,仅供读者参 ...

  5. mongo 唯一约束索引_mongodb索引详解(Indexes)

    索引介绍 索引在mongodb中被支持,如果没有索引,mongodb必须扫描每一个文档集合选择匹配的查询记录.这样扫描集合效率并不高,因为它需要mongod进程使用大量的数据作遍历操作. 索引是一种特 ...

  6. access建立两个字段唯一索引_面试官:谈谈你对mysql索引的认识?

    引言 这篇我们就来谈谈关于索引方面的mysql面试题.还是老规矩,讲的是在Innodb存储引擎下的情形,毕竟我还真没用过Mysiam之类的存储引擎. ps:其实很早就想写了,一直偷懒! 其实这下面每个 ...

  7. 面试mysql中怎么创建索引_阿里面试:MySQL如何设计索引更高效?

    有情怀,有干货,微信搜索[三太子敖丙]关注这个不一样的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. ...

  8. 2 创建联合索引_想进大厂,这些Mysql索引底层知识你是必须知道的

    推荐学习 阿里P8MySQL,基础/索引/锁/日志/调优都不误,一锅深扒端给你 最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发 前言 这一篇是讲解Mysql中做使用 ...

  9. java mysql索引_如何理解并正确使用MySql索引

    1.概述 索引是存储引擎用于快速查找记录的一种数据结构,通过合理的使用数据库索引可以大大提高系统的访问性能,接下来主要介绍在MySql数据库中索引类型,以及如何创建出更加合理且高效的索引技巧. 注:这 ...

最新文章

  1. 实心和空心哪个抗弯能力强_空心砖4大优缺点一次看 便宜耐用营造大自然原始风...
  2. 【AAAI2022】TLogic:时序知识图谱上可解释链接预测的时间逻辑规则
  3. 卷积神经网络的实际意义
  4. 最短路模板 - Floyd / Dijkstra
  5. python零基础怎么学-零基础python入门分析,如何做到一个月学会(深思极恐)
  6. 2018及以后的热门网络技巧
  7. java中的23种设计模式_Java开发中的23种设计模式详解
  8. 从零开始搭建自己的VueJS2.0+ElementUI单页面网站(一、环境搭建)
  9. 前端学习(3011):vue+element今日头条管理--关于编辑器代码段
  10. mysql root命令_MySQL 修改 root 密码命令
  11. 一周学会Mootools 1.4中文教程:(4)类型
  12. three 查看版本号
  13. 计算机专业自我简介50字,2021年个人简历自我评价50字
  14. julia集 matlab代码,Julia集分形
  15. stm32 串口2空闲中断死机_STM32串口空闲中断问题
  16. 英语学习思路【罗肖尼Shawney】
  17. Windows 10 配置OpenGL ES 3.0 环境
  18. Qemu 调试内核 出错 Remote 'g' packet reply is too long:
  19. java 局域网文件拷贝文件_局域网使用Java进行文件传输
  20. 按图搜索获取1 6 8 8 商品(拍立淘)

热门文章

  1. 产品认知:你的产品适不适合快速去迭代?
  2. python object has no attribute_如何修复python中的“AttributeError:type object has no attribute”?...
  3. C orm mysql_Simple MySQL-C ORM
  4. mac设置首页访问php,mac系统下php项目除了首页全访问不了
  5. workbook加载文件路径_通过Workbook.XML 修复Excel自定义名称
  6. java计算面积的方法_JAVA多态计算面积main函数调用方法
  7. Mysql身份认证漏洞及利用(CVE-2012-2122)
  8. 绕过 WAF:绕过一些 WAF 设备的 Burp 插件
  9. docker安装clickhouse_clickhouse ----入门
  10. ant vue 兼容性问题_ant design for vue 关于table的一些问题