MongoDB 索引原理与索引优化
转载请注明出处:
1.MongoDB索引
索引通常能够极大的提高查询的效率, 如果没有索引, MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的, 特别在处理大量的数据时, 查询可以要花费几十秒甚至几分钟, 这对网站的性能是非常致命的。
索引是特殊的数据结构, 索引存储在一个易于遍历读取的数据集合中, 索引是对数据库表中一列或多列的值进行排序的一种结构。
2.MongoDB索引说明
索引数据通过 B 树来存储,从而使得搜索的时间复杂度为 O(logdN) 级别的(d 是 B 树的度, 通常 d 的值比较大,比如大于 100),比原先 O(N) 的复杂度大幅下降。这个差距是惊人的,以一个实际例子来看,假设 d=100,N=1亿,那么 O(logdN) = 8, 而 O(N) 是 1亿。是的,这就是算法的威力。
索引本身是在高速缓存当中,相比磁盘 IO 操作会有大幅的性能提升。(需要注意的是,有的时候数据量非常大的时候,索引数据也会非常大,当大到超出内存容量的时候,会导致部分索引数据存储在磁盘上,这会导致磁盘 IO 的开销大幅增加,从而影响性能,所以务必要保证有足够的内存能容下所有的索引数据)
当然,事物总有其两面性,在提升查询速度的同时,由于要建立索引,所以写入操作时就需要额外的添加索引的操作,这必然会影响写入的性能,所以当有大量写操作而读操作比较少的时候,且对读操作性能不需要考虑的时候,就不适合建立索引。当然,目前大多数互联网应用都是读操作远大于写操作,因此建立索引很多时候是非常划算和必要的操作。
3.为什么使用B-Tree
B树有以下特点
B树在查询中的比较是在内存中完成的,相比磁盘IO的速度,内存中的比较耗时几乎可以忽略。所以只要树的高度足够低,IO次数足够少,就可以提升查找性能。
B树为了插入一个元素,多个节点发生了连锁改变,会有一定的性能损耗,但也正因为如此,B树能够始终维持多路平衡。这也是B树的另外一大优势:自平衡。
查找的元素在不同的结点(根结点、中间结点、叶子结点),性能会有一定差别,因此查询性能不稳定。
范围查找性能不高。
我们知道二叉查找树查询的时间复杂度是O(logN),查找速度最快和比较次数最少,既然性能已经如此优秀,但为什么实现索引是使用B-Tree而不是二叉查找树,关键因素是磁盘IO的次数。
磁盘读取依靠的是机械运动,分为寻道时间、旋转延迟、传输时间三个部分,这三个部分耗时相加就是一次磁盘IO的时间,大概9ms左右。这个成本是访问内存的十万倍左右。正是由于磁盘IO是非常昂贵的操作,所以数据库性能优化的核心思想是降低磁盘IO次数。
说明: 普通的机械盘HDD一次磁盘IO的时间大概是9ms; 普通SSD一次磁盘IO耗时大概是0.2ms(IOPS:5000); PCIe卡一次磁盘IO耗时大概是0.05ms(IOPS:20000);
从二叉树的查找过程了来看,最坏的情况下磁盘IO的次数由树的高度来决定。要减少磁盘IO的次数就必须要压缩树的高度,让瘦高的树尽量变成矮胖的树,所以B-Tree就在这样伟大的时代背景下诞生了。
4.MongoDB 索引优化:explain
语法
db_name.table_Name.find({query}).explain(cond)
参数
名称 | 描述 |
---|---|
db_name | 数据库名 |
table_Name | 集合名 |
query | 查询条件 |
cond | 查询计划所使用的参数 |
返回值
参数 | 含义 |
---|---|
plannerVersion | 查询计划版本 |
namespace | 要查询的集合 |
indexFilterSet | 是否使用索引 |
parsedQuery | 查询条件,此处为x=1 |
winningPlan | 最佳执行计划 |
stage | 查询方式,见下表 |
filter | 过滤条件 |
direction | 搜索方向 |
rejectedPlans | 拒绝的执行计划 |
serverInfo | MongoDB服务器信息 |
stage说明
参数 | 含义 |
---|---|
COLLSCAN | 全表扫描 |
IXSCAN | 索引扫描 |
FETCH | 根据索引去检索文档 |
SHARD_MERGE | 合并分片结果 |
IDHACK | 针对 _id 进行查询 |
2.executionStats:executionStats会返回执行计划的一些统计信息
参数 | 含义 |
---|---|
executionSuccess | 是否执行成功 |
nRetured | 返回的文档数 |
executionTimeMillis | 执行耗时 |
totalKeysExamined | 索引扫描次数 |
totalDocsExamined | 文档扫描次数 |
stage | 扫描方式,具体可选值与上下的相同 |
nRetured | 查询document获得数据的时间 |
executionTimeMillsEstimate | 检索document获得数据的时间 |
inputStage.executionTimeMillisEstimate | 该查询扫描文档index所用时间 |
works | 工作单元数,一个查询会分解成小的工作单元 |
advanced | 优先返回的结果数 |
docsExamined | 文档检查数目,与totalDocsExamined一致,检查了总共的document个数,从而返回上面的nReturned数量 |
在实际分析索引问题是否最优的时候,主要查看executionStats.totalKeysExamined、
executionStats.totalDocsExamined、executionStats .nReturned三个统计项,如果存在以下情况则说明索引存在问题,可能索引不是最优的:
executionStats.totalKeysExamine远大于executionStats .nReturned
executionStats. totalDocsExamined远大于executionStats .nReturned
MongoDB 索引原理与索引优化的更多相关文章
- php面试专题---Mysql索引原理及SQL优化
php面试专题---Mysql索引原理及SQL优化 一.总结 一句话总结: 注意:只写精品 1.为表设置索引要付出代价 是什么? 存储空间:一是增加了数据库的存储空间 修改插入变动索引时间:二是在插入 ...
- MySQL索引原理及SQL优化
目录 索引(Index) 索引的原理 b+树 MySQL如何使用索引 如何优化 索引虽好,不可滥用 如何验证索引使用情况? SQL优化 explain查询执行计划 id select_type tab ...
- 【mysql】索引原理-MySQL索引原理以及查询优化
转载:https://www.cnblogs.com/bypp/p/7755307.html 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性 ...
- 索引原理-btree索引与hash索引的区别
btree索引与hash索引的区别,之前不清楚,mark一下. Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree索引需要从根节点到枝节点,最后才能访问到页节点这样多 ...
- mysql索引原理及创建与查询
索引介绍 一:为什么要有索引 索引是用来优化查询效率(速度)的 没有索引的话,对于大数据的表,就只能每次都遍历一遍,数据量越大,耗时越多有索引的话,可以提升好几个数量级的速度 一般的应用系统,读写比例 ...
- 「 MySQL高级篇 」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- 「MySQL高级篇」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- MongoDB优化,建立索引实例及索引机制原理讲解
MongoDB优化,建立索引实例及索引机制原理讲解 为什么需要索引? 当你抱怨MongoDB集合查询效率低的时候,可能你就需要考虑使用索引了,为了方便后续介绍,先科普下MongoDB里的索引机制(同样 ...
- MongoDB · 引擎特性 · MongoDB索引原理
MongoDB · 引擎特性 · MongoDB索引原理数据库内核月报原文链接 http://mysql.taobao.org/monthly/2018/09/06/ 为什么需要索引?当你抱怨Mong ...
- mysql_索引原理及优化
思考: 我们知道mysql最好的数据存储量级是百万级别,是的往往在百万级别或者几十万级别就会出现慢查询(我对慢查询的定义是大于1秒),几年前我所在的一个做pos机支付的联机交易的核心系统组,当时就做过 ...
随机推荐
- P7476 苦涩 题解
Link 一道很好的复杂度均摊题目. 只需要考虑删除操作时的时间复杂度.保证复杂度的重点之一是精确定位到所有包含最大值的区间,即不去碰多余的区间.每次删除操作会删除若干个整个区间,以及至多两个区间被删 ...
- LOJ2324「清华集训 2017」小Y和二叉树
题目链接 瞎jb贪一发就过了.首先度数<=2且编号最小的点一定是中序遍历最靠前的点,我们从这个点开始dfs一遍算出子树中度数<=2且编号最小的点记为\(f(i)\),然后从这个点开始一步一 ...
- sql面试50题------(11-20)
文章目录 11.查询至少有一门课与学号为'01'的学生所学课程相同的学生的学号和姓名 12.查询和'01'号同学所学课程完全相同的其他同学的学号 13.查询两门及其以上不及格课程的同学的学号,姓名及其 ...
- 你真的会使用Typora吗?
你真的会使用Typora吗? 标题 一级标题:# 空格+内容 二级标题:## 空格+内容 字体 加粗:内容两边各加两个*号 你真美! 斜体:内容两边各加一个*号 你真帅! 删除线:两边各加两个~号(波 ...
- 用 VS Code 搞 Qt6:信号、槽,以及QObject
Qt 里面的信号(Signal)和槽(Slot)虽然看着像事件,但它实际上是用来在两个对象之间进行通信的.既然是通信,就会有发送者和接收者. 1.信号是发送者,触发时通过特有的关键字"emi ...
- 论文笔记 - Active Learning by Acquiring Contrastive Examples
Motivation 最常用来在 Active Learning 中作为样本检索的两个指标分别是: 基于不确定性(给模型上难度): 基于多样性(扩大模型的推理空间). 指标一可能会导致总是选到不提供有 ...
- 如何在bat中进入虚拟环境
很多情况下我们希望在项目中建立一个build.bat用于项目的自动构建,避免每次构建时都需要手动在控制台中输入命令. 例如对于 pyinstall 的项目,只需要如下的实现: pyinstaller ...
- python 的time、datetime模块
python 时间模块 import datetime res = datetime.datetime.now() print(res) # 2022-08-07 16:47:07.120459 ...
- Jmeter之聚合报告“造假”
通过Jmeter,模拟一个"虚假"的聚合报告,可"应付"日常现场项目的性能测试验收.本文档着重介绍jmeter的固定定时器,通过设置随机的延迟时间(如想业务场景 ...
- 记一次线上频繁fullGc的排查解决过程
发生背景 最近上线的一个项目几乎全是查询业务,并且都是大表的慢查询,sql优化是做了一轮又一轮,前几天用户反馈页面加载过慢还时不时的会timeout,但是我们把对应的sql都优化一遍过后,前台响应还是 ...