对比mongodb查询的执行计划,说一说组合索引的优化方案(下)

一、接着上文

上文已说到totalIds在or查询条件中,所以不会匹配到索引。

本文我们试着调整下查询条件,观察调整后,特别是totalIds字段,将匹配哪个索引。(观察的依据仍是查询计划的executionStats)

  • 把totalIds从or查询条件中提取出来
// 调整前
"$or": [{ "auth": 1 },{ "totalIds": { "$in": [10001] } }
]// 调整后
{ "totalIds": { "$in": [10001] } }

实际业务调整,让请求客户端,选择两者中的任意一个条件。这样,就需要写or条件了。

至于auth查询条件,想要查询变快,可以创建索引auth_1_createdOn_0,另外缩短查询的时间范围。(我们近一年auth=1的数据量不过2000条)

本文的主要内容是针对totalIds字段如何匹配索引,以及使用哪个组合索引。

二、新的执行计划

执行的步骤是(由内往外):IXSCAN -> FETCH -> OR -> FETCH -> SORT_KEY_GENERATOR -> SORT -> PROJECTION

可以看到,查询耗时提高了至少百倍,只需要37毫秒,检索的索引数量由十几万减少到几百。

'executionStats': {'nReturned': 4,'executionTimeMillis': 37,'totalKeysExamined': 486,'totalDocsExamined': 486,'executionStages': {'stage': "SINGLE_SHARD",'nReturned': 4,'executionTimeMillis': 37,'totalKeysExamined': 486,'totalDocsExamined': 486,'totalChildMillis': NumberLong("37"),'shards': [{'shardName': "d-bp1cef3c8241a8a4",'executionSuccess': true,'executionStages': {'stage': "PROJECTION",'nReturned': 4,'executionTimeMillisEstimate': 1,'works': 495,'advanced': 4,'needTime': 489,'needYield': 0,'saveState': 34,'restoreState': 34,'isEOF': 1,'invalidates': 0,'transformBy': {'$sortKey': {'$meta': "sortKey"}},'inputStage': {'stage': "SORT",'nReturned': 4,'executionTimeMillisEstimate': 1,// 略'inputStage': {'stage': "SORT_KEY_GENERATOR",'nReturned': 4,'executionTimeMillisEstimate': 1,// 略'inputStage': {'stage': "FETCH",'filter': {// 略},'nReturned': 4,'executionTimeMillisEstimate': 1,// 略'inputStage': {'stage': "OR",'nReturned': 486,'executionTimeMillisEstimate': 0,// 略'inputStages': [{'stage': "FETCH",'filter': {'recycle': {'$eq': null}},'nReturned': 0,'executionTimeMillisEstimate': 0,// 略'inputStage': {'stage': "IXSCAN",'nReturned': 0,'executionTimeMillisEstimate': 0,// 略}},{'stage': "IXSCAN",'nReturned': 486,'executionTimeMillisEstimate': 0,// 略}]}}}}}}]}
},
  • IXSCAN

查询语句匹配到了索引totalIds_1_isDelete_1_recycle_1_creatorName_1,其中 ‘isMultiKey’: true, 因为totalIds是一个数组。

'stage': "IXSCAN",
'nReturned': 486,
'executionTimeMillisEstimate': 0,
'works': 487,
'advanced': 486,
'needTime': 0,
'needYield': 0,
'saveState': 34,
'restoreState': 34,
'isEOF': 1,
'invalidates': 0,
'keyPattern': {'totalIds': 1.0,'isDelete': 1.0,'recycle': 1.0,'creatorName': 1.0
},
'indexName': "totalIds_1_isDelete_1_recycle_1_creatorName_1",
'isMultiKey': true,
'multiKeyPaths': {'totalIds': ["totalIds"],'isDelete': [],'recycle': [],'creatorName': []
},
'isUnique': false,
'isSparse': false,
'isPartial': false,
'indexVersion': 2,
'direction': "forward",
'indexBounds': {'totalIds': ["[10001, 10001]"],'isDelete': ["[false, false]"],'recycle': ["[0, 0]"],'creatorName': ["[MinKey, MaxKey]"]
},
'keysExamined': 486,
'seeks': 1,
'dupsTested': 486,
'dupsDropped': 0,
'seenInvalidated': 0

OR

“第一个”FETCH和IXSCAN两个stage之间是OR关系。这里的IXSCAN和上一个stage相同。

这里说它是“第一个”FETCH,因为外层还有一个FETCH。

本阶段主要是针对recycle查询条件,这也提醒我们在编程的时候,对字段不要赋空,要赋一个默认状态的值。

就拿本例的recycle字段为例:

  • 保存记录的时候,recycle=0
  • 放入回收站的时候,recycle=1
  • 从回收站还原的时候,recycle=0

如此,recycle字段的值要么是0,要么是1。

而查询条件也就可以优化,不存在or查询了。

// 修改前
{"$or":[{"recycle":null},{"recycle":0}]}// 修改后
{"recycle":0}

在这里插入图片描述

“第二个”FETCH

和前文不同,根据创建时间区间检索,由IXSCAN阶段改为FETCH阶段了。

'stage': "FETCH",
'filter': {'$and': [{'createdOn': {'$lte': ISODate("2024-04-29T00:00:00.000Z")}},{'createdOn': {'$gte': ISODate("2023-04-28T00:00:00.000Z")}},{'classroomName': {'$regex': ".*大口加小口.*"}}]
},

SORT

SORT排序是在内存中进行排序,所以它的速度非常快。

在这里插入图片描述

三、组合索引的差异

前文,我们说了,包含totalIds字段的组合索引有两个:

  • totalIds_1_isDelete_1_recycle_1_creatorName_1
  • totalIds_1_createdOn_2

mongodb匹配的是前者,而非后者。(个人认为,Mongo应该是根据组合索引匹配的字段数量来,前者匹配了三个字段,而后者是两个字段)

这也给我们建组合索引提了个醒,不要像我们这样,一通下来,期望匹配的索引(totalIds_1_createdOn_2)反而落榜了。

如果你想要指定使用索引totalIds_1_createdOn_2,在末尾指定hint(“totalIds_1_createdOn_2”)
见下所示:
在这里插入图片描述

当然,对于本查询来说,只要查询条件totalIds匹配了索引,由于其区分度非常高,最后的查询效率都很高。(查询只需几十毫秒)

下面说一说,当指定使用索引totalIds_1_createdOn_2时,执行计划变成怎么样了。

执行步骤为(由内往外):IXSCAN --> FETCH --> SORT_KEY_GENERATOR --> SORT --> PROJECTION

"winningPlan" : {"stage" : "PROJECTION","transformBy" : {"$sortKey" : {"$meta" : "sortKey"}},"inputStage" : {"stage" : "SORT","sortPattern" : {"createdOn" : -1},"limitAmount" : 20,"inputStage" : {"stage" : "SORT_KEY_GENERATOR","inputStage" : {"stage" : "FETCH","filter" : {// 略},"inputStage" : {"stage" : "IXSCAN","keyPattern" : {"totalIds" : 1,"createdOn" : 1},"indexName" : "totalIds_1_createdOn_2","isMultiKey" : true,"multiKeyPaths" : {"totalIds" : ["totalIds"],"createdOn" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"totalIds" : ["[MinKey, MaxKey]"],"createdOn" : ["[MinKey, MaxKey]"]}}}}}}

最内层的索引数据检索,使用了我们指定的索引totalIds_1_createdOn_2。

四、总结

通过两篇文章,我们举例一个集合的多个组合索引,对比分析其执行计划。
因为只有执行计划,才是判定你的查询语句最后是否使用了索引,以及哪个索引。

最后,当一个字段被包含在多个组合索引的时候,更加要小心了,因为我们程序是不会指定使用哪个索引。

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

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

相关文章

【Web UI自动化】Python+Selenium 环境配置

安装Python 官网地址:https://www.python.org/,Downloads菜单下选择适合自己的系统版本,我的是Windows。 点击进入以后,可以看到当前最新版本。 点击上面的链接,页面下滑,找到下载链接,根据…

特斯拉PIXCELL矩阵大灯擎耀远程控制技术照亮未来智能之光

在科技的浪潮中,特斯拉这个名字如同一道闪电,照亮了新能源汽车的天空。而在这片星空中,特斯拉PIXCELL矩阵大灯则如同一颗璀璨的星辰,以其独特的创新技术和卓越的性能,为驾驶者提供了前所未有的照明体验。矩阵大灯技术如…

【团体程序设计天梯赛】往年关键真题 L2-036 网红点打卡攻略 模拟 L2-037 包装机 栈和队列 详细分析完整AC代码

【团体程序设计天梯赛 往年关键真题 详细分析&完整AC代码】搞懂了赛场上拿下就稳 【团体程序设计天梯赛 往年关键真题 25分题合集 详细分析&完整AC代码】(L2-001 - L2-024)搞懂了赛场上拿下就稳了 【团体程序设计天梯赛 往年关键真题 25分题合…

ElasticSearch教程入门到精通——第二部分(基于ELK技术栈elasticsearch 7.x新特性)

ElasticSearch教程入门到精通——第二部分(基于ELK技术栈elasticsearch 7.x新特性) 1. JavaAPI-环境准备1.1 新建Maven工程——添加依赖1.2 HelloElasticsearch 2. 索引2.1 索引——创建2.2 索引——查询2.3 索引——删除 3. 文档3.1 文档——重构3.2 文…

基于Matlab使用深度学习的多曝光图像融合

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在图像处理领域,多曝光图像融合技术是一种重要的技术,它可以将不同曝光条件下…

mysql优化面试总结

mysql优化 和 mysql优化之索引 两篇文章有大量的实验性的内容,我暂时没时间理解,把八股部分总结到这篇文章中,方便记忆 我们为什么要对sql进行优化 我们开发项目上线初期,由于业务数据量相对较少,一些SQL的执行效率对…

基于EBAZ4205矿板的图像处理:03使用VIO调试输出HDMI视频图像

基于EBAZ4205矿板的图像处理:03使用VIO调试输出HDMI视频图像 在zynq调试时VIO是真的方便,特此写一篇博客记录一下 先看效果 项目简介 下面是我的BD设计,vtc用于生成时序,注意,2021.2的vivado的vtcIP是v6.2版本&…

移植USB RTL8723DU WIFI无线驱动给RK3588

wifi 通过dmesg发现可以识别到设备为无线网卡,并驱动蓝牙,但是在ifconfig中没有找到对应的wlan0。 推断有可能是内核里面没有针对8723du wifi的驱动。所以需要查询当前的5.10内核是否包含8723du的驱动。到https://linux-hardware.org/ 上查看。 并结合…

机器学习:深入解析SVM的核心概念【一、间隔与支持向量】

直接阅读原始论文可能有点难和复杂,所以导师直接推荐我阅读周志华的《西瓜书》!!然后仔细阅读其中的第六章:支持向量机 间隔与支持向量 **问题一:什么叫法向量?为什么是叫法向量**什么是法向量?…

Nginx配置Https缺少SSL模块

1、Linux下Nginx配置https nginx下载和安装此处就忽略,可自行百度 1.1、配置https 打开nginx配置文件 vim /opt/app/nginx/conf/nginx.conf相关https配置 server {listen 443 ssl; #开放端口server_name echarts.net;#域名#redirect to https#ssl on; #旧版#ssl证…

【嵌入式笔试题】网络编程笔试题

非常经典的笔试题。 2.网络编程(29道) 2.1列举一下OSI协议的各种分层。说说你最熟悉的一层协议的功能。 ( 1 )七层划分为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理 层。 ( 2 )五层划分为:应用层、传输层、网络层、数据链路层、物理层。 ( 3 )…

爬虫学习--1.前导知识

初始爬虫 前言引入 随着大数据时代的来临,网络爬虫在互联网中的地位将越来越重要。互联网中的数据是海量的,如何自动高效地获取互联网中我们感兴趣的信息并为我们所用是一个重要的问题,而爬虫技术就是为了解决这些问题而生的。 我们感兴趣的信息分为不同的类型:如果只是做…