MongoDB进阶篇-索引(索引概述、索引的类型、索引相关操作、索引的使用)

文章目录

  • 1. 索引概述
  • 2. 索引的类型
    • 2.1 单字段索引
    • 2.2 复合索引
    • 2.3 其他索引
      • 2.3.1 地理空间索引(Geospatial Index)
      • 2.3.2 文本索引(Text Indexes)
      • 2.3.3 哈希索引(Hashed Indexes)
  • 3. 索引相关操作
    • 3.1 查看索引
    • 3.2 创建索引
      • 3.3.1 创建单字段索引
      • 3.3.2 创建复合索引
      • 3.3.3 创建文本索引
    • 3.4 移除索引
      • 3.4.1 移除指定索引
      • 3.4.2 移除所有索引
  • 4. 索引的使用
    • 4.1 执行计划
    • 4.2 执行计划中各个字段的含义
    • 4.3 stage字段的取值及含义
    • 4.4 覆盖查询

阅读本文前可以先阅读以下文章:

  • MongoDB快速入门(MongoDB简介、MongoDB的应用场景、MongoDB中的基本概念、MongoDB的数据类型、MongoDB的安装与部署、MongoDB的常用命令)
  • MongoDB的常用命令(数据库操作、集合操作、文档操作)

1. 索引概述

MongoDB 索引的官网文档:索引-MongoDB手册


索引支持在 MongoDB 中高效执行查询。如果没有索引,MongoDB 就必须扫描集合中的每个文档以返回查询结果。如果查询存在适当的索引,MongoDB 就可以使用该索引来限制其必须扫描的文档数

索引可提高查询性能,但添加索引会影响写入操作的性能。对于写入读取率高的集合,由于每次插入操作都必须同时更新所有索引,因此会带来较高的索引成本

MongoDB 索引使用 B-Tree 数据结构(MySQL 是 B+Tree)

2. 索引的类型

2.1 单字段索引

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

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

2.2 复合索引

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

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

2.3 其他索引

2.3.1 地理空间索引(Geospatial Index)

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

2.3.2 文本索引(Text Indexes)

文本索引的特点:

  • 分词:MongoDB 在创建文本索引时会对字段内容进行分词处理,将文本分解成单词或术语(tokens)
  • 权重:可以为不同的字段指定不同的权重,以便在搜索时影响文档的相关性得分
  • 停用词:MongoDB 会忽略某些常用词(如 “the”、“and” 等),这些词被称为停用词。MongoDB 有一个内置的停用词列表,也可以自定义停用词列表
  • 语言支持:MongoDB 的文本索引支持多种语言的分词和搜索

注意事项:

  • 文本索引不存储停止词和词干。这意味着它们不会影响索引的大小
  • 文本索引不能用于文本字段中的二进制数据
  • 文本索引不能用于数组字段中的字符串元素
  • $text 查询不能与 $$$ 运算符一起使用

2.3.3 哈希索引(Hashed Indexes)

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

3. 索引相关操作

3.1 查看索引

查看索引的语法

db.collection.getIndexes()

查看 comment 集合中所有的索引

db.collection.getIndexes()

查询结果如下

[ { v: 2, key: { _id: 1 }, name: '_id_' } ]

结果中显示的是默认的 _id_ 索引(MongoDB 在创建集合的过程中,会在 _id 字段上创建一个唯一的索引,默认名字为 _id_,该索引可防止插入两个具有相同 _id 值的文档)

  • _id 索引是唯一索引,因此 _id 值不能重复
  • 在分片集群中,通常使用 _id 作为片键

3.2 创建索引

创建索引的语法

db.collection.createIndex(keys, options)
参数名类型描述必需
keys文档指定索引的字段和索引类型。对于文本索引,字段类型应该设置为 "text"。可以指定单个字段或多个字段
options文档索引的额外选项。这是一个可选参数,可以包含多个字段

options 参数的详细说明:

选项类型描述默认值
background布尔是否在后台创建索引。如果为 true,MongoDB 将在后台创建索引,这样就不会阻塞其他数据库操作false
unique布尔是否创建唯一索引。如果为 true,则索引字段的值必须是唯一的false
name字符串索引的名称。如果未指定,MongoDB 会自动生成一个名称自动生成
partialFilterExpression文档指定部分索引的过滤条件。只有满足条件的文档才会包含在索引中
sparse布尔是否创建稀疏索引。如果为 true,则索引只包含具有指定字段的文档,忽略没有该字段的文档false
expireAfterSeconds整数对于具有日期类型的字段,指定文档在集合中的生存时间(TTL)
storageEngine文档指定索引的存储引擎配置使用默认存储引擎配置
weights文档对于文本索引,为索引中的每个字段指定权重。权重越高,字段在文本搜索中的相关性得分越高所有字段权重相等

3.3.1 创建单字段索引

对 user_id 字段建立单字段索引

db.comment.createIndex({ user_id: 1 });

再次查看 comment 集合中所有的索引

[{ v: 2, key: { _id: 1 }, name: '_id_' },{ v: 2, key: { user_id: 1 }, name: 'user_id_1' }
]

3.3.2 创建复合索引

对 user_id 和 nickname 建立复合(Compound)索引

db.comment.createIndex({ userid: 1, nickname: -1 });

再次查看 comment 集合中所有的索引

[{ v: 2, key: { _id: 1 }, name: '_id_' },{ v: 2, key: { user_id: 1 }, name: 'user_id_1' },{v: 2,key: { userid: 1, nickname: -1 },name: 'userid_1_nickname_-1'}
]

3.3.3 创建文本索引

对 content 字段建立单字段索引

db.comment.createIndex({ content: "text" });

3.4 移除索引

3.4.1 移除指定索引

db.collection.dropIndex(index);

删除 comment 集合中 user_id 字段上的升序索引

db.comment.dropIndex({ user_id: 1 }
);

3.4.2 移除所有索引

db.collection.dropIndexes()

删除 comment 集合中的所有索引

db.comment.dropIndexes()

_id 的字段的索引是无法删除的,只能删除非 _id 字段的索引

4. 索引的使用

4.1 执行计划

分析查询性能(Analyze Query Performance)通常使用执行计划(Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等

db.collection.find(query,options).explain(options)
参数名类型描述必需
querydocument查询选择器,用于指定查询条件
optionsdocument可选的。用于修改查询的默认行为的各种选项,如排序、限制等
explainfunction用于获取查询执行计划的详细信息是(调用时)
explainOptionsdocument可选的。用于修改解释操作的默认行为的各种选项

每个参数的详细解释:

  • query: 这是一个文档,用于定义查询条件。它可以是简单的字段等值查询,也可以是复杂的条件组合,包括逻辑运算符和正则表达式
  • options: 这是一个文档,可以包含多个键,用于控制查询的行为。常见的选项包括:
    • sort: 排序条件
    • limit: 限制返回的文档数量
    • skip: 跳过文档的数量。
    • projection: 投影,用于指定返回的字段
  • explain: 这是一个函数,当你在查询后面调用它时,MongoDB 不会返回查询结果,而是返回查询执行计划的详细信息。这有助于理解查询是如何执行的,以及如何优化查询
  • explainOptions: 这是一个文档,用于控制解释操作的输出。例如,可以指定是否返回所有阶段的执行计划或者只返回获胜计划

根据 user_id 字段查询数据

db.comment.find({ user_id: "1003" }).explain();

MongoDB 返回的结果

{explainVersion: '1',queryPlanner: {namespace: 'test.comment',parsedQuery: {user_id: {'$eq': '1003'}},indexFilterSet: false,queryHash: 'B7F3AE51',planCacheKey: '8C1EE785',optimizationTimeMillis: 0,maxIndexedOrSolutionsReached: false,maxIndexedAndSolutionsReached: false,maxScansToExplodeReached: false,prunedSimilarIndexes: false,winningPlan: {isCached: false,stage: 'COLLSCAN',filter: {user_id: {'$eq': '1003'}},direction: 'forward'},rejectedPlans: []},command: {find: 'comment',filter: {user_id: '1003'},'$db': 'test'},serverInfo: {host: 'LAPTOP-G7HILK54',port: 27017,version: '8.0.3',gitVersion: '89d97f2744a2b9851ddfb51bdf22f687562d9b06'},serverParameters: {internalQueryFacetBufferSizeBytes: 104857600,internalQueryFacetMaxOutputDocSizeBytes: 104857600,internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,internalDocumentSourceGroupMaxMemoryBytes: 104857600,internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,internalQueryProhibitBlockingMergeOnMongoS: 0,internalQueryMaxAddToSetBytes: 104857600,internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600,internalQueryFrameworkControl: 'trySbeRestricted',internalQueryPlannerIgnoreIndexWithCollationForRegex: 1},ok: 1
}

重点关注 winningPlan 中的 stage 字段(COLLSCAN 表示全盘扫描)

在这里插入图片描述

下面对 user_id 字段建立索引

db.comment.createIndex({ user_id: 1 });

再次查看执行计划

{explainVersion: '1',queryPlanner: {namespace: 'test.comment',parsedQuery: {user_id: {'$eq': '1003'}},indexFilterSet: false,queryHash: 'B7F3AE51',planCacheKey: '57E4C731',optimizationTimeMillis: 0,maxIndexedOrSolutionsReached: false,maxIndexedAndSolutionsReached: false,maxScansToExplodeReached: false,prunedSimilarIndexes: false,winningPlan: {isCached: false,stage: 'FETCH',inputStage: {stage: 'IXSCAN',keyPattern: {user_id: 1},indexName: 'user_id_1',isMultiKey: false,multiKeyPaths: {user_id: []},isUnique: false,isSparse: false,isPartial: false,indexVersion: 2,direction: 'forward',indexBounds: {user_id: ['["1003", "1003"]']}}},rejectedPlans: []},command: {find: 'comment',filter: {user_id: '1003'},'$db': 'test'},serverInfo: {host: 'LAPTOP-G7HILK54',port: 27017,version: '8.0.3',gitVersion: '89d97f2744a2b9851ddfb51bdf22f687562d9b06'},serverParameters: {internalQueryFacetBufferSizeBytes: 104857600,internalQueryFacetMaxOutputDocSizeBytes: 104857600,internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,internalDocumentSourceGroupMaxMemoryBytes: 104857600,internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,internalQueryProhibitBlockingMergeOnMongoS: 0,internalQueryMaxAddToSetBytes: 104857600,internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600,internalQueryFrameworkControl: 'trySbeRestricted',internalQueryPlannerIgnoreIndexWithCollationForRegex: 1},ok: 1
}

可以发现,stage 字段已经变成了 FETCH,inputStage 属性里面的 stage 字段变成了 IXSCAN(基于索引的扫描)

在这里插入图片描述

4.2 执行计划中各个字段的含义

字段名描述
explainVersion解释输出的版本号。
queryPlanner查询计划器的详细信息。
namespace执行查询的命名空间(数据库和集合)。
parsedQuery解析后的查询条件。
indexFilterSet是否设置了索引过滤器。
queryHash查询的哈希值。
planCacheKey用于查询缓存的键。
optimizationTimeMillis查询优化所花费的时间(毫秒)。
maxIndexedOrSolutionsReached是否达到了索引 OR 解决方案的最大数量。
maxIndexedAndSolutionsReached是否达到了索引 AND 解决方案的最大数量。
maxScansToExplodeReached是否达到了索引爆炸扫描的最大数量。
prunedSimilarIndexes是否修剪了相似的索引。
winningPlan被选中的查询计划。
isCached是否从计划缓存中检索到计划。
stage查询执行的阶段。
inputStage当前阶段的输入阶段(用于嵌套阶段)。
keyPattern索引的键模式。
indexName索引的名称。
isMultiKey索引是否是多键索引。
multiKeyPaths包含多键路径的索引字段。
isUnique索引是否是唯一索引。
isSparse索引是否是稀疏索引。
isPartial索引是否是部分索引。
indexVersion索引的版本。
direction索引扫描的方向。
indexBounds索引扫描的边界。
rejectedPlans被拒绝的查询计划列表。
command执行的命令的详细信息。
serverInfo服务器信息,包括主机名、端口、版本等。
serverParameters影响查询执行的服务器参数。
ok命令是否成功执行的标志。

4.3 stage字段的取值及含义

阶段名称描述
COLLSCAN集合扫描,即全集合扫描,没有使用索引。
IXSCAN索引扫描,使用索引来查找文档。
FETCH获取阶段,用于检索索引扫描后找到的文档的其余字段。
SHARD_MERGE在分片集群中,合并来自不同分片的查询结果。
SORT排序阶段,对结果进行排序。
LIMIT限制阶段,限制返回的文档数量。
SKIP跳过阶段,跳过指定数量的文档。
IDHACK对于 _id 的查询,MongoDB 可以使用特殊的优化。
SHARDING_FILTER在分片集群中,用于过滤掉不属于当前查询的分片数据的阶段。
PROJECTION投影阶段,只返回文档中的特定字段。
TEXT文本搜索阶段,用于文本索引的搜索。
GEONEAR地理空间查询阶段,用于查找最接近某个点的文档。
GEOFILTER地理空间过滤阶段,用于过滤地理空间查询的结果。
COUNT计数阶段,用于 count 操作。
COUNT_SCAN使用索引进行计数扫描的阶段。
COUNT_SCAN_WITH_FILTER使用索引进行计数扫描,并且应用过滤器的阶段。
DISTINCT_SCAN用于 distinct 操作的索引扫描阶段。
SUBPLAN子计划阶段,用于处理复杂查询的一部分。
IXHASH使用散列索引的阶段。
FORCED_SCAN强制进行集合扫描,即使存在索引。
COVERED索引覆盖查询,所有需要的字段都在索引中,不需要回表查询。
EOF查询结束。

4.4 覆盖查询

当查询条件和查询的投影仅包含索引字段时,MongoDB 会直接从索引返回结果,而不扫描任何文档或将文档带入内存,这些覆盖的查询非常高效(类似于 MySQL 中的覆盖索引)


db.comment.find({ user_id: "1003" },{ user_id: 1, _id: 0 }
).explain();

MongoDB 返回的结果

{explainVersion: '1',queryPlanner: {namespace: 'test.comment',parsedQuery: {user_id: {'$eq': '1003'}},indexFilterSet: false,queryHash: 'DC80EEEF',planCacheKey: 'B8237218',optimizationTimeMillis: 0,maxIndexedOrSolutionsReached: false,maxIndexedAndSolutionsReached: false,maxScansToExplodeReached: false,prunedSimilarIndexes: false,winningPlan: {isCached: false,stage: 'PROJECTION_COVERED',transformBy: {user_id: 1,_id: 0},inputStage: {stage: 'IXSCAN',keyPattern: {user_id: 1},indexName: 'user_id_1',isMultiKey: false,multiKeyPaths: {user_id: []},isUnique: false,isSparse: false,isPartial: false,indexVersion: 2,direction: 'forward',indexBounds: {user_id: ['["1003", "1003"]']}}},rejectedPlans: []},command: {find: 'comment',filter: {user_id: '1003'},projection: {user_id: 1,_id: 0},'$db': 'test'},serverInfo: {host: 'LAPTOP-G7HILK54',port: 27017,version: '8.0.3',gitVersion: '89d97f2744a2b9851ddfb51bdf22f687562d9b06'},serverParameters: {internalQueryFacetBufferSizeBytes: 104857600,internalQueryFacetMaxOutputDocSizeBytes: 104857600,internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,internalDocumentSourceGroupMaxMemoryBytes: 104857600,internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,internalQueryProhibitBlockingMergeOnMongoS: 0,internalQueryMaxAddToSetBytes: 104857600,internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600,internalQueryFrameworkControl: 'trySbeRestricted',internalQueryPlannerIgnoreIndexWithCollationForRegex: 1},ok: 1
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何给 Apache 新站点目录配置 SELinux ?

在 web 服务器管理领域,确保服务器环境的安全性至关重要。SELinux (Security-Enhanced Linux) 是保护 Linux 服务器最有效的工具之一,它是一种强制访问控制 (MAC mandatory access control) 安全机制。当使用最流行的 web 服务器 Apache 提供 web 内容时…

Elasticsearch 开放推理 API 增加了对 IBM watsonx.ai Slate 嵌入模型的支持

作者:来自 Elastic Saikat Sarkar 使用 Elasticsearch 向量数据库构建搜索 AI 体验时如何使用 IBM watsonx™ Slate 文本嵌入。 Elastic 很高兴地宣布,通过集成 IBM watsonx™ Slate 嵌入模型,我们的开放推理 API 功能得以扩展,这…

【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制

博客主页: [小ᶻZ࿆] 本文专栏: 前端 文章目录 💯前言💯案例背景💯逻辑运算符的优先级与短路求值运算符优先级的概念短路求值的概念 💯分析案例代码的执行过程第一步:执行 && 运算第二步&#…

2024年11月21日Github流行趋势

项目名称:twenty 项目维护者:charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍:正在构建一个由社区支持的现代化Salesforce替代品。项目star数:21,798项目fork数:2,347 项目名称:p…

【算法】计算程序执行时间(C/C++)

引言 我们在写算法时要考虑到算法的执行效率,有的题目规定了时间限制,我们需要在这个时间之内去解决问题。如果我们需要比对算法的好坏,就需要输出这个程序运行了多长时间。 在C或C中计算程序执行时间,可以使用多种方法&#xf…

【题解】—— LeetCode一周小结46

🌟欢迎来到 我的博客 —— 探索技术的无限可能! 🌟博客的简介(文章目录) 【题解】—— 每日一道题目栏 上接:【题解】—— LeetCode一周小结45 11.切棍子的最小成本 题目链接:1547. 切棍子的最…

PH热榜 | 2024-11-22

DevNow 是一个精简的开源技术博客项目模版,支持 Vercel 一键部署,支持评论、搜索等功能,欢迎大家体验。 在线预览 1. Lovable 标语:全球首位全栈人工智能工程师 介绍:GPT工程师已在140多个国家拥有超过5万用户&#…

时序论文23|ICML24谷歌开源零样本时序大模型TimesFM

论文标题:A DECODER - ONLY FOUNDATION MODEL FOR TIME - SERIES FORECASTING 论文链接:https://arxiv.org/abs/2310.10688 论文链接:https://github.com/google-research/timesfm 前言 谷歌这篇时间序列大模型很早之前就在关注&#xff…

【UCIE协议系列-1】

UCIE协议系列-1 1 UCIE背景1.1 UCIE产生背景1.2 UCIE主要特性 2 UCIE分层协议2.1 Protocol 层2.1.1 Mode VS protocal2.1.2 PCIe 6.02.1.2.1 Raw Mode for PCIe 6.02.1.2.2 Flit Mode: Standard 256B Flit for PCIe 6.0 2.1.3 CXL3.0 256B Flit Mode2.1.3.1 Raw Mode for CXL 2…

智能安全配电装置在高校实验室中的应用

​ 摘要:高校实验室是科研人员进行科学研究和实验的场所,通常会涉及到大量的仪器设备和电气设备。电气设备的使用不当或者维护不周可能会引发火灾事故。本文将以一起实验室电气火灾事故为例,对事故原因、危害程度以及防范措施进行分析和总结…

ESP8266 STA模式TCP客户端 电脑手机网络调试助手

1.STA模式TCP客户端和电脑网络调试助手 2.STA模式TCP客户端和手机网络调试助手

高中-信息技术科目考试-编程题

(24上)1.为了响应国家低碳的倡议,学校请你设计一个饮料瓶回收系统,根据投的饮料瓶类型和数量进行奖励。具体如下图:假设学生投瓶10个,投瓶类型定义为t(0表示塑料瓶,1表示易拉罐&…

如何将文件Copy到Docker镜像中

如何将文件Copy到Docker镜像中 一、使用Dockerfile的COPY指令二、使用Docker CP命令三、使用Docker Volume四、综合应用Docker作为一种轻量级的容器化技术,在软件开发和部署中得到了广泛应用。在使用Docker时,经常需要将本地文件或目录复制到Docker镜像中,以便在容器内部使用…

Figma入门-文字、样式、链接、动作

Figma入门-文字、样式、链接、动作 前言 在之前的工作中,大家的原型图都是使用 Axure 制作的,印象中 Figma 一直是个专业设计软件。 最近,很多产品朋友告诉我,很多原型图都开始用Figma制作了,并且很多组件都是内置的…

shell编程(8) until循环以及函数基本创建调用

声明!!! 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章 视频链接:泷羽sec 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 # until循环 脚本代码: i0 until [ ! $i -lt 1…

NVR管理平台EasyNVR多品牌NVR管理工具的流媒体视频融合与汇聚管理方案

随着信息技术的飞速发展,视频监控已经成为现代社会安全管理和业务运营不可或缺的一部分。无论是智慧城市、智能交通、还是大型企业、校园安防,视频监控系统的应用都日益广泛。NVR管理平台EasyNVR,作为功能强大的流媒体服务器软件,…

fastadmin实现站内通知功能

实现效果如下 application/admin/view/common/header.html <style>#notificationMenu {display: none;position: absolute;top: 40px;right: 0;background: #fff;border-radius: 6px;padding: 10px 0;width: 300px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);z-inde…

大语言模型---LoRA中损失值的计算

文章目录 概要损失计算流程小结 概要 Llama-7B模型的LoRA微调训练中&#xff0c;通过使用Cross-Entropy Loss来度量模型输出的预测分布和真实标签分布之间的距离&#xff0c;来衡量模型的准确性。 本文主要介绍LoRA中损失值的计算流程。 Cross-Entropy Loss作用&#xff1a;是…

【Vue】指令扩充(指令修饰符、样式绑定)

目录 指令修饰符 按键修饰符 事件修饰符 双向绑定指令修饰符 输入框 表单域 下拉框 单选按钮 复选框 样式绑定 分类 绑定class 绑定style tab页切换示例 指令修饰符 作用 借助指令修饰符&#xff0c;可以让指令的功能更强大 分类 按键修饰符&#xff1a;用来…

集成金蝶云星空数据至MySQL的完整案例解析

金蝶云星空数据集成到MySQL的技术案例分享 在企业信息化系统中&#xff0c;数据的高效流动和准确同步是确保业务连续性和决策支持的重要环节。本文将聚焦于一个具体的系统对接集成案例——金蝶云星空的数据集成到MySQL&#xff0c;方案名称为“2金蝶物料同步到商城中间表”。 …