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机支付的联机交易的核心系统组,当时就做过 ...
随机推荐
- 非Navicat破解延长14天试用时间
延长Navicat使用时长 Navicat作为一套多连接数据库开发工具,十分好用,购买正版太过昂贵,破解版过于麻烦,有时候还会有安全问题,好在我们有14天的试用时间,我们可以从这个方面入手 对于有能力 ...
- python字典推导&&列表推导&&输出随机数
字典推导: x = ['A', 'B', 'C', 'D'] y = ['Alice', 'Bob', 'Cecil', 'David'] print({i:j for i,j in zip(x,y) ...
- 微粒群算法PSO 01背包问题 python
import random import math import matplotlib.pyplot as plt import numpy as np import time def init(b_ ...
- Android开发 对接微信分享SDK总结
原文:Android开发 对接微信分享SDK总结 - Stars-One的杂货小窝 公司项目需要对接微信分享,本来之前准备对接友盟分享的,但友盟的分享实际参数太多,而我又只需要对接一个微信分享,于是便 ...
- Redis可视化管理工具-RedisDesktopManager
Windows客户端,访问Redis数据库并执行一些基本操作. 链接:https://pan.baidu.com/s/1OuGqIfbpGwglC-642rECbQ 提取码:m6uo
- 利用递归的方式在JSON 数据中找到某个节点的多有父节点
在项目中遇到的问题-- 一个级联题,知道答案id 后将每一级的选项展示出来 例如 级联题的 json 数据是 [ { name: '北京', id: 1, children:[ { name: '朝 ...
- freeswitch的mod_curl模块
概述 有时候,我们需要在呼叫的过程中,或过程后调用web api接口. freeswitch的mod_curl模块可以很方便的实现web api的接口调用. mod_curl模块默认不安装,需要进入模 ...
- cookie中 防止重复存值 (可用于历史记录等)
function makeCookie($key,$val){ // 查看cookie中是否已经存过键为history_ids if(Cookie::has($key)){ // 已经存过了 $jso ...
- lvm+xfs的扩缩容
ext4文件系统可以经行扩缩容操作,但xfs的文件系统只能扩容,无法缩容 所以如果需要进行xfs的缩容,可以先使用xfsdump备份文件系统,然后对逻辑卷(/分区)进行缩容操作(此时原xfs文件系统会 ...
- 【GUI开发案例】用python爬百度搜索结果,并开发成exe桌面软件!
一.背景介绍 你好,我是 @马哥python说 ,一名10年程序猿. 1.1 老版本 之前我开发过一个百度搜索的python爬虫代码,具体如下: [python爬虫案例]用python爬取百度的搜索结 ...