MongoDB笔记03-MongoDB索引

文章目录

  • 一、前言
    • 1.1 概述
    • 1.2 MongoDB索引使用B-Tree还是B+Tree?
    • 1.3 B 树和 B+ 树的对比
    • 1.4 总结
  • 二、索引的类型
    • 2.1 单字段索引
    • 2.2 复合索引
    • 2.3 其他索引
  • 三、索引的管理操作
    • 3.1 索引的查看
    • 3.2 索引的创建
      • 3.2.1 单字段索引
      • 3.2.2 复合索引
    • 3.3 索引的移除
      • 3.3.1 指定索引的移除
      • 3.3.2 所有索引的移除
  • 四、 索引的使用
    • 4.1 执行计划
    • 4.2 涵盖的查询


在这里插入图片描述

一、前言

1.1 概述

  • 索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
  • 如果查询存在适当的索引,MongoDB可以使用该索引限制必须检查的文档数。
  • 索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果。
  • 官网文档:https://docs.mongodb.com/manual/indexes/

1.2 MongoDB索引使用B-Tree还是B+Tree?

MongoDB索引在查看资料的时候有些地方说使用是B-Tree,有些地方说是B+Tree)
因此使用db.serverStatus()查看默认使用的存储引擎

> db.serverStatus()
..."storageEngine" : {"name" : "wiredTiger","supportsCommittedReads" : true,"supportsSnapshotReadConcern" : true,"readOnly" : false,"persistent" : true},
...

可以看到MongoDB使用的存储引擎是wiredTiger,而wiredTiger使用的是 B+ 树作为其存储结构
而之所以有B-Tree还是B+Tree的争论,可能是从 MongoDb 3.2 版本开始,其使用了 WiredTiger 作为其默认的存储引擎。而MongoDb 3.2 版本之前可能使用 B 树作为存储的数据结构。
相关文档:https://www.mongodb.com/zh-cn/docs/manual/core/wiredtiger/

1.3 B 树和 B+ 树的对比

B 树
内部节点:内部节点既存储键(keys),也存储值(values)。
叶子节点:叶子节点存储键值对。
适用场景:适合点查(精确匹配)和少量范围查询。
B+ 树
内部节点:内部节点只存储键(keys),不存储值(values)。
叶子节点:所有值(values)都存储在叶子节点中,叶子节点之间形成一个有序的链表。
适用场景:适合范围查询和顺序访问

1.4 总结

B树的树内存储数据,因此查询单条数据的时候,B树的查询效率不固定,最好的情况是O(1)。我们可以认为在做单一数据查询的时候,使用B树平均性能更好。但是,由于B树中各节点之间没有指针相邻,因此B树不适合做一些数据遍历操作。
B+树的数据只出现在叶子节点上,因此在查询单条数据的时候,查询速度非常稳定。因此,在做单一数据的查询上,其平均性能并不如B树。但是,B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。

参考文章:
https://www.cnblogs.com/rjzheng/p/12316685.html
https://zhuanlan.zhihu.com/p/519658576

二、索引的类型

2.1 单字段索引

MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。

对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引
在这里插入图片描述

2.2 复合索引

MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index)。

复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后在每个userid的值内,再在按score倒序排序。
在这里插入图片描述

2.3 其他索引

地理空间索引(Geospatial Index)、文本索引(Text Indexes)、哈希索引(Hashed Indexes)。

地理空间索引(Geospatial Index)
为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。

文本索引(Text Indexes)
MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”),而将集合中的词作为词干,只存储根词。

哈希索引(Hashed Indexes)
为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。

注意:
当查询条件比较多,同时要提高性能时,使用复合索引
索引也是一个小集合,会占用空间,如果创建很多索引,会影响插入效率。

三、索引的管理操作

3.1 索引的查看

说明:
返回一个集合中的所有索引的数组。

语法:

db.collection.getIndexes()

注意:该语法命令运行要求是MongoDB 3.0+

【示例】
查看comment集合中所有的索引情况

> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"}
]

结果中显示的是默认 _id 索引。

默认_id索引:
MongoDB在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 id ,该索引可防止客户端插入两个具有相同值的文档,您不能在_id字段上删除此索引。

注意:该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键

3.2 索引的创建

说明:
在集合上创建索引。

语法:

db.collection.createIndex(keys, options)

参数:

参数类型说明
keysdocument包含字段和值对的文档,其中字段是索引键,值描述该字段的索引类型。对于字段上的升序索引,请指定值1;对于降序索引,请指定值-1。比如: {字段:1或-1} ,其中1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。另外,MongoDB支持几种不同的索引类型,包括文本、地理空间和哈希索引。
optionsdocument可选。包含一组控制索引创建的选项的文档。.

注意:
在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() ,之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

3.2.1 单字段索引

示例:对 userid 字段建立索引:

> db.comment.createIndex({userid:1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"},{"v" : 2,"key" : {"userid" : 1},"name" : "userid_1","ns" : "articledb.comment"}
]

建立索引时的参数:按升序创建索引

在mongodb-compass中也可以看到创建的索引
在这里插入图片描述

3.2.2 复合索引

对 userid 和 nickname 同时建立复合(Compound)索引:

> db.comment.createIndex({userid:1,nickname:-1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 2,"numIndexesAfter" : 3,"ok" : 1
}
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"},{"v" : 2,"key" : {"userid" : 1},"name" : "userid_1","ns" : "articledb.comment"},{"v" : 2,"key" : {"userid" : 1,"nickname" : -1},"name" : "userid_1_nickname_-1","ns" : "articledb.comment"}
]

mongodb-compass中查看
在这里插入图片描述

3.3 索引的移除

说明:可以移除指定的索引,或移除所有索引

3.3.1 指定索引的移除

语法:

db.collection.dropIndex(index)

参数:

参数类型说明
indexstring or document指定要删除的索引。可以通过索引名称或索引规范文档指定索引。若要删除文本索引,请指定索引名称。

【示例】
删除 comment 集合中 userid 字段上的升序索引:

> db.comment.dropIndex({userid:1})
{ "nIndexesWas" : 3, "ok" : 1 }> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"},{"v" : 2,"key" : {"userid" : 1,"nickname" : -1},"name" : "userid_1_nickname_-1","ns" : "articledb.comment"}
]

删除复合索引

 > db.comment.dropIndex("userid_1_nickname_-1"){ "nIndexesWas" : 2, "ok" : 1 }> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"}
]

3.3.2 所有索引的移除

语法:

db.comment.dropIndexes()

【示例】
删除 comment 集合中所有索引

> db.comment.dropIndexes()
{"nIndexesWas" : 1,"msg" : "non-_id indexes dropped for collection","ok" : 1
}
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "articledb.comment"}
]

注意: _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。

四、 索引的使用

4.1 执行计划

分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。
那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
语法:

db.collection.find(query,options).explain(options)

【示例】
查看根据userid查询数据的情况:

> db.comment.find({userid:"1003"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "articledb.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "COLLSCAN","filter" : {"userid" : {"$eq" : "1003"}},"direction" : "forward"},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "SKY-20211222SVF","port" : 27017,"version" : "4.0.12","gitVersion" : "5776e3cbf9e7afe86e6b29e22520ffb6766e95d4"},"ok" : 1
}

注意: "stage" : "COLLSCAN", 表示全集合扫描

下面对userid建立索引

> db.comment.createIndex({userid:1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}
> db.comment.find({userid:"1003"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "articledb.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "FETCH","inputStage" : {"stage" : "IXSCAN","keyPattern" : {"userid" : 1},"indexName" : "userid_1","isMultiKey" : false,"multiKeyPaths" : {"userid" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"userid" : ["[\"1003\", \"1003\"]"]}}},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "SKY-20211222SVF","port" : 27017,"version" : "4.0.12","gitVersion" : "5776e3cbf9e7afe86e6b29e22520ffb6766e95d4"},"ok" : 1
}

compass查看:
在这里插入图片描述

4.2 涵盖的查询

Covered Queries
当查询条件和查询的投影仅包含索引字段时,MongoDB直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。(类似mysql不用回表扫描)
在这里插入图片描述
更多:https://docs.mongodb.com/manual/core/query-optimization/#read-operations-covered-query

【示例】

> db.comment.find({userid:"1003"},{userid:1,_id:0})
{ "userid" : "1003" }
{ "userid" : "1003" }
> db.comment.find({userid:"1003"},{userid:1,_id:0}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "articledb.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "PROJECTION","transformBy" : {"userid" : 1,"_id" : 0},"inputStage" : {"stage" : "IXSCAN","keyPattern" : {"userid" : 1},"indexName" : "userid_1","isMultiKey" : false,"multiKeyPaths" : {"userid" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"userid" : ["[\"1003\", \"1003\"]"]}}},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "SKY-20211222SVF","port" : 27017,"version" : "4.0.12","gitVersion" : "5776e3cbf9e7afe86e6b29e22520ffb6766e95d4"},"ok" : 1
}

compass查看:
在这里插入图片描述


全部文章:
MongoDB笔记01-概念与安装
MongoDB笔记02-MongoDB基本常用命令
MongoDB笔记03-MongoDB索引
MongoDB笔记04-SpringBoot整合MongoDB

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10832.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

肿瘤治疗评价指标太多?一文帮你梳理清楚!|个人观点·24-11-09

小罗碎碎念 如何延长癌症患者存活时间、提高生存质量、减轻肿瘤带来的痛苦,是评价抗癌药物的重要标准,而把这些标准落在数据上就诞生了各项“评价指标”。 在肿瘤治疗领域,有OS、PFS、RFS、TTP、TTF、ORR、DCR、DDC等各项评价指标。对于大部…

保研考研机试攻略:python笔记(3)

🐨🐨🐨11sort 与 sorted 区别 sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。 list 的 sort 方法返回的是对已经存在的列表进行操作, 无返回值,而内建函数 sorted 方法返回的…

Linux之自定义shell和C标准库函数

自定义shell和C标准库函数 一.自定义xshell1.1main函数主体1.2获取用户信息以及命令串1.3判断命令串是否为空串1.4判断是否为重定向1.5分割命令串1.6判断是否为内建命令1.7执行命令 二.自定义C标准库函数2.1mystdio.h2.2mystdio.c2.3main.c 一.自定义xshell 1.1main函数主体 1…

TeamTalk知识点梳理一(单聊)

文章目录 db_proxy_serverdb_proxy_server reactor响应处理流程连接池redis连接池MySQL连接池 单聊消息消息如何封装?如何保证对端完整解析一帧消息?协议格式?单聊消息流转流程消息序号(msg_id )为什么使用redis生成&a…

带跳转功能的电子产品目录如何制作?

​在数字化时代,电子产品已成为我们生活和工作中不可或缺的伙伴。为了方便用户快速查找所需产品,带跳转功能的电子产品目录应运而生。本文将详细介绍如何制作一个高效便捷的带跳转功能电子产品目录,让用户轻松实现产品查找、筛选和购买。 1.要…

从0开始linux(26)——动静态库

欢迎来到博主的专栏:从0开始linux 博主ID:代码小豪 文章目录 如何写一个静态库动态库动静态链接 c/c程序形成可执行程序,需要经过三个步骤,编译、汇编、链接三个步骤,我们之前做链接时,使用的方法是将头文件…

hexo 搭建个人博客网站

hexo搭建个人博客 文章目录 hexo搭建个人博客摘要搭建网站的前置工具WebStormHexo Hexo配置初始化本地运行 主题更改安装butterfly主题 正式上线GitHub Pages配置新建仓库SSH密钥配置 将hexo部署到GitHub 个性化设置后续网站更新内容分类和标签设置分类(categories&…

BLDC基础知识复习【二】

如果采用20毫欧的电流采样电阻,10A的电流计算出来时0.2V,这个显然还是太小了,需要运放放大并且加上偏置: 6组换向程序: 最核心的控制逻辑在这里:在main.c里面对PWM占空比进行设置,通过一个指针在…

1130 - Host ‘10.0.0.1‘ is not allowed to connect to this MySQL server

1130 - Host 10.0.0.1 is not allowed to connect to this MySQL server 一、1130 - Host 10.0.0.1 is not allowed to connect to this MySQL server二、1130 - Host 10.0.0.1 is not allowed to connect to this MariaDB serverendl 一、1130 - Host ‘10.0.0.1’ is not all…

构建智慧城市:数字孪生技术的发展之路

基于数字孪生的智慧城市发展是一种革命性的城市转型模式,旨在将物理世界与数字世界融合,在数字平台上建立城市的虚拟映像,从而实现对城市运行状态、资源利用、环境影响等方面的综合管理和优化。这种发展模式将数字技术深度融入城市规划、建设…

金融行业信息流投放方法论及金融客户投放案例

失血2024,金融行业进入“极寒”,广告投放也不例外。 受金融政策管控,在渠道投放受限也颇多,创意文案及素材上审核异常严格,整体投放成本高…… 金融理财信息流广告投放,如带着“镣铐”跳舞,束…

Unity-Yaml-Dot-Net诗歌篇-如何像雷总学习写代码像诗歌-MVC 框架,+注入Inject +状态机生命周期

我们是否可以像雷总一样 大家都说他的代码,像诗一样优雅 一个MVC 框架,加注入 (以下内容其实和雷总没什么关系,也和雷总当年代码毫无关系,不过先“阅读理解”一下) 雷总-写的代码像似一个优雅??!!^^ R…

安卓好软-----电脑端查看apk全部信息的工具 查看包名 名称以及权限等等

有时候从网络下载的应用很多是英文。时间久了会忘记到底是什么apk应用。这款工具可以方便的查看apk应用的名称 包名以及各种权限 图标 大小版本号等等。方便用户随时查看 APK Helper能够详细地获得安装包名、软件名称、APK证书、真实版本号、要求的手机版本、系统权限、以及证书…

分布式唯一ID生成(四):tinyid

文章目录 本系列前言号段模式多DB支持tinyid-client 本系列 漫谈分布式唯一ID分布式唯一ID生成(二):leaf分布式唯一ID生成(三):uid-generator分布式唯一ID生成(四):tiny…

JavaWeb:文件上传2

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

April tag坐标定义

朝右的方向为x轴正向, 朝下的方向为y轴正方向, z 轴垂直纸面向里。 4个角点的坐标定义如下图所示。

江行智能×图扑软件:输煤皮带数字孪生管控系统

在现代矿业和电力行业中,输煤皮带系统是运输环节的核心。然后,随着智能化生产的高要求,智慧矿山输煤皮带系统的传统管理模式已显得力不从心。产业引入的三维可视化和数字孪生技术,一改传统输煤皮带系统由于设备老化、管理不善等原…

【Python】从入门开始抓取你想要的电影,一周可掌握基础,附完整源码

Python学习很简单,只是你走进了误区。 为什么你一定要先掌握枯燥的基础点后,再去做实际操作呢? 其实,你根本坚持不了那么长时间,但实际上你可以直接去做python项目。 不信?看看我做这个项目的思路&#x…

【C++】map和set的介绍及使用

前言: map和 set 是 C STL(标准模板库)中的两种非常重要的容器,它们基于一种叫做平衡二叉搜索树(通常是红黑树)的数据结构来实现。在 C 中,map 是一个键值对容器,set 只存储唯一的键…

NumPy 数组属性

1.NumPy 数组的基本属性 NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度,一维数组的秩为 1,二维数组的秩为 2,以此类推。NumPy中,每个线性的数组称为轴(axis…