文档章节

快速掌握mongoDB(三)——mongoDB的索引详解

SEOwhywhy
 SEOwhywhy
发布于 07/19 15:42
字数 2525
阅读 4
收藏 0

  1 mongoDB索引的管理
  
  2 mongoDB中常用的索引类型
  
  1 单键索引
  
  2 复合索引
  
  3 多键索引
  
  4 哈希索引
  
  3 mongoDB中常用的索引属性
  
  1  唯一索引
  
  2  局部索引
  
  2 稀疏索引
  
  4 TTL索引
  
  回到顶部
  
  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:www.tdcqpt.cn'张三'}).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:'www.dongfangyuld.com jack',age:20},
  
  {name:'tom',age:22},
  
  {name:'lilei',age:25}]
  
  },
  
  {
  
  "classname":"class2",
  
  "students":[{name:www.fushengyul.com  '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(www.baikayule.cn{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.www.yfylhl.com createIndex({address:1}www.jmaguojiyL.com ,{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(www.leyouzaixan.cn),msg:"log2"},
  
  {_id:3,createtime:new Date(www.haojiangyule.com),msg:"log3"},
  
  {_id:4,createtime:new Date(www.yfykLe2019.com),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和一些地理位置相关的索引,这里不再介绍,有兴趣的小伙伴可以到官网 研究下。如果文中有错误的话,希望大家可以指出,我会及时修改,谢谢。

© 著作权归作者所有

SEOwhywhy
粉丝 8
博文 152
码字总数 335019
作品 0
私信 提问
阿里专家视频课限时抢!精讲+实操12节课学懂MongoDB数据库!

想要学习MongoDB却不知道如何入门? 漫天的培训课程却无一讲解实战案例? 云栖社区联手阿里云大学独家出品—— 阿里云MongoDB技术负责人、MongoDB中文社区联席主席联合操刀 12期精讲+实操,全...

a独家记忆
2018/07/12
0
0
基于云数据库MongoDB版进行应用开发

MongoDB是一个基于分布式文件存储的数据库,在互联网、物联网、游戏、金融等领域被广泛采用。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是当前最流行的Nosql...

mcy0425
2018/09/14
28
0
MongoDB 3.0新特性概述

MongoDB 在 2015年3月3日 跳过了 MongoDB 2.8版本,直接在 MongoDB 2.6版本后,发布了MongoDB 3.0版本。 随后在 2015年3月17日 发布了 MongoDB 3.0.1 版本; 在 2015年4月9日发布了 MongoDB ...

xinsir999
2018/05/02
0
0
MongoDB系列教程(八):GridFS存储详解

MongoDB系列教程(八):GridFS存储详解 GridFS简介 mongoDB的文档以BSON格式存储,支持二进制的数据类型,当我们把二进制格式的数据直接保存到mongoDB的文档中。但是当文件太大时,例如图片...

开元中国2015
2015/07/25
373
0
快速掌握mongoDB(三)——mongoDB的索引详解

  1 mongoDB索引的管理      2 mongoDB中常用的索引类型      1 单键索引      2 复合索引      3 多键索引      4 哈希索引      3 mongoDB中常用的索引属性   ...

SEOwhywhy
07/19
17
0

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
10
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
1K
11
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部