说一说mongodb组合索引的匹配规则
一、背景
有一张1000多万条记录的大表,需要做归档至历史表,出现了大量慢查询。
查询条件是
"classroomId": {$in: ["xxx", "xxx", ..... "xxx","xxx", "xxx" ] }
耗时近5秒,且是全表扫描

为什么没有使用到任何索引呢?
请看该集合创建的索引有哪些:

建立了两个组合索引userId_1_classroomId_1_isDelete_1和userId_1_classroomId_1,
但是二者的重复度极高。(可以删掉userId_1_classroomId_1_isDelete_1,再新建一个单索引classroomId_1)
二、组合索引
1、最左匹配原则
MongoDB 中组合索引遵循最左匹配原则,即在检索数据时从复合索引的最左边开始匹配。
举例来说,上文的组合索引userId_1_classroomId_1,对于查询条件 {“userId”: “xxx”, “classroomId”: “xxx”} 可以匹配该组合索引,因为查询条件包含了索引的最左前缀;而对于查询条件 {“classroomId”:“xxx”} 则无法匹配该组合索引。
但是对查询条件 {“userId”: “xxx”} 则可以匹配该组合索引。
所以,我们需要再新建一个单索引classroomId_1。
2、ESR规则
ESR(Equality, Sort, Range)规则是创建高效组合索引的一个重要原则
- Equality(相等):将需要精确匹配的字段放在索引的前面。这些字段用于过滤数据,减少需要扫描的文档数量。例如查询 db.xxx.find({“classroomId”: “GM03DI890”}) 中,classroomId 字段是精确匹配,应放在索引的前面。
- Sort(排序):排序操作应放在精确匹配字段之后。因为精确匹配可以减少需要排序的文档数量,且这样可以让 MongoDB 进行非阻塞排序。例如查询 db.xxx.find({“classroomId”: “GM03DI890”}).sort({createdOn: 1}) 中,createdOn 字段用于排序,应放在 classroomId 字段之后。
也就是说,组合索引的顺序应该是classroomId_1_createdOn_1 - Range(范围):范围查询字段应放在索引的最后面。范围查询会扫描一定范围内的数据,将其放在最后可以提高查询效率。例如查询 db.xxx.find({price: {$gte: 15000}}) 中,price 字段是范围查询,应放在索引的最后。
三、OR查询
如果是OR查询呢?
还是举如下例:
{"$or": [{"auth": 1},{"totalIds": {"$in": [1002482]}}]
}
应该分别对 auth 和 totalIds 字段创建单独的索引,而不是创建一个组合索引。
db.xxx.createIndex({"auth":1}, {"name":"auth_1","background":true})
db.xxx.createIndex({"totalIds":1}, {"name":"totalIds_1","background":true})
这是因为 MongoDB 在使用 or 查询时,如果每个子句都有自己的索引,那么 MongoDB 可以分别使用这些索引来执行查询,然后合并结果。这通常比创建一个包含所有字段的复合索引更有效。
1、区分度问题
区分度低的字段-- auth 字段的值只有两个(0 和 1),区分度很低。通常情况下,区分度低的字段单独建立索引的收益较小,因为索引的目的是快速定位数据,而区分度低的字段在索引中并不能有效减少需要扫描的数据量。
但我们还得考虑另外一个因素。
2、查询频率
如果 auth 字段在查询中非常频繁地被使用,即使区分度低,建立索引也可能带来一些性能提升。例如,如果大部分查询都包含 auth 字段,那么建立索引可以减少全表扫描的次数。
对于 or 查询,MongoDB 会分别使用每个子查询的索引,然后合并结果。
因此,为 auth 和 totalIds 分别建立单独的索引是合理的。这样可以确保每个子查询都能高效地使用索引。
四、执行计划
使用 explain 分析查询计划:
可以通过 explain 方法来分析查询计划,查看是否使用了索引以及索引的使用情况。
{"planSummary":"IXSCAN { totalIds: 1 }, IXSCAN { auth: 1 }"}
db.xxx.find({"$or":[{"auth":1},{"totalIds":{"$in":[636622]}}]}).explain("executionStats")

从执行计划可以看到,现在的OR查询能够使用到这两个单独索引。
五、总结
本文在OR查询中使用了分别创建两个单独索引来提高查询效率。
这里有一个问题,auth字段的区分度低,而totalIds字段的区分度高。
在索引及文档扫描的时候,整个查询的效率是取决于auth字段,尽管totalIds查询速度快。

上述OR查询语句,索引扫描行数以及文档扫描行数均为18000多。

从中也可以看出,区分度高和低,影响的检索效率高低。
改进:
- 从业务角度,考虑将auth查询与非auth查询分开来查询,这样就不会有OR查询场景
- 从数据库的角度,可以考虑分两张表,当要查询auth=0还是1的时候,从小表查询;如果没有auth查询,就可以使用totalIds字段,由于其区分度高,可以大大提高检索效率。
相关文章:
说一说mongodb组合索引的匹配规则
一、背景 有一张1000多万条记录的大表,需要做归档至历史表,出现了大量慢查询。 查询条件是 "classroomId": {$in: ["xxx", "xxx", ..... "xxx","xxx", "xxx" ] }耗时近5秒,且…...
Maven核心插件之maven-resources-plugin
前言 Maven 插件是 Maven 构建系统的重要组成部分,它们为 Maven 提供了丰富的功能和扩展能力,使得 Maven 不仅是一个构建工具,更是一个强大的项目管理平台。在 Maven 项目中,插件的使用通常通过配置 pom.xml 文件来完成。每个插件…...
C++ 鼠标轨迹算法 - 防止游戏检测
一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…...
网络学习记录6
查找下一跳和流量如何通过,是网络路由的基本概念。下面我会尽量用通俗易懂的方式来解释这个过程。 查找下一跳 数据包的目的地:当一个数据包在网络中传输时,它的目标是一个特定的IP地址。 路由表的作用:路由器有一个叫做路由表的东…...
【数学】概率论与数理统计(四)
文章目录 [toc] 分布函数分布函数性质离散型随机变量的分布函数连续型随机变量的分布函数示例1问题解答 正态随机变量示例问题解答 示例2问题(1)(2) 解答(1)(2) 随机变量函数的分布离…...
小结:华为交换机常用的操作指令
以下是华为交换机常用的操作指令总结,按功能分类说明: 1. 系统管理 进入系统视图system-view返回用户视图quit保存配置save查看当前配置display current-configuration重启设备reboot2. 用户管理 配置用户密码local-user <username> password ir…...
轻松学51单片机--基于普中科技开发板练习蓝桥杯及机器人大赛等(8-DS1302实时时钟)
1、DS1302 DS1302是一款实时时钟芯片,可以用于实时计时和日期显示等应用。它具有低功耗、精度高、芯片体积小等特点,非常适合嵌入式系统和小型电子设备中使用。 DS1302具有多个功能和特性,包括: 时钟功能:可以显示年…...
《Java核心技术II》并行流
并行流 从集合中获取并行流:Stream paralleWords words.parallelStream(); parallel方法将任意顺序流转换为并行流:Stream paralleWords Stream.of(wordArray).parallel(); 以下是不好的示范,假设对字符串的所有短单词计数: …...
Vue 3前端与Python(Django)后端接口简单示例
项目 后端(Django)前端(Vue 3) 后端(Django) 创建Django项目和应用: 确保你已经安装了Django。如果没有安装,可以使用以下命令安装: pip install django创建一个新的Dja…...
《拉依达的嵌入式\驱动面试宝典》—操作系统篇(二)
《拉依达的嵌入式\驱动面试宝典》—操作系统篇(二) 你好,我是拉依达。 感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。 《拉…...
STM32和国民技术(N32)单片机串口中断接收数据及数据解析
一、串口配置 根据单片机不同,串口IO口配置也不同,像STM32单片机,RX脚可以配置为复用输出,也可以配置为浮空输入模式。但是国民技术单片机(N32)的RX是不能配置为复用输出模式的,这样是收不到数…...
【人工智能】大语言模型的微调:让模型更贴近你的业务需求
大语言模型的微调:让模型更贴近你的业务需求 随着大语言模型(LLM, Large Language Model)如 GPT-4、BERT 和 T5 等的广泛应用,模型的微调(Fine-tuning)技术成为实现领域专属任务的重要手段。通过微调&…...
大语言模型的稀疏性:提升效率与性能的新方向
大语言模型的稀疏性:提升效率与性能的新方向 大语言模型(LLM, Large Language Model)随着参数规模的不断扩大,其性能得到了显著提升,但也带来了巨大的计算和存储开销。稀疏性(Sparsity)作为一种…...
Linux Bridge与Open vSwitch的工作原理及协作
在虚拟化和云计算环境中,Linux Bridge和Open vSwitch(OVS)都是用于构建虚拟网络的关键组件。它们提供了二层交换功能,并且能够将虚拟机或容器连接到物理网络中。然而,两者在实现细节和技术特性上有所不同,下…...
async++源码阅读——task模块
1、task_base.h 本人将自己的理解以注释的形式添加的代码中,方便需要的时候重新复习。该文件中用到的一些技术: 该文件中的类并没有使用virtual,而是自定义了需函数表,但是并没有放到每个对象的开始位置,而是通过指针…...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(五)
文章目录 一、学生管理模块功能实现1、添加学生功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、学生管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码…...
EF Core一对一和多对多
目录 EF Core一对一 关系属性 关系配置 使用 EF Core多对多 关系属性 关系配置 使用 EF Core一对一 关系属性 必须显式的在其中一个实体类中声明一个外键属性,可以在Order建立Delivery,也可以在Delivery建立OrderId class Order {public long…...
记一次sealos部署k8s集群之delete了第一台master如何恢复
记一次sealos部署k8s集群之delete了第一台master如何恢复 一、背景描述 使用sealos部署了一套K8S集群 master信息:172.27.100.1、172.27.100.2、172.27.100.3 node信息:172.27.100.4、172.27.100.5 sealos安装在172.27.100.1节点,根目录下/root/.sealos/文件还在! [root…...
vue3+vite+ts集成第三方js
npm run dev可以正常运行和测试。但是npm run build会报错。 要实现引入静态js,避免使用全局变量报错。 1. HTML 引入第三方 JS 在你的 HTML 文件中,通过 <script> 标签引入一个本地第三方 JS 文件,例如: <script sr…...
android framework.jar 在应用中使用
在开发APP中,有时会使用系统提供的framework.jar 来替代 android.jar, 在gradle中配置如下: 放置framework.jar 依赖配置 3 优先级配置 gradle.projectsEvaluated {tasks.withType(JavaCompile) {Set<File> fileSet options.bootstrapClasspat…...
proteus新手福音:用快马平台轻松生成第一个电路仿真项目
作为一个刚接触电子电路设计的萌新,第一次打开Proteus时真的被满屏的英文界面和密密麻麻的元件库吓到了。直到发现了InsCode(快马)平台,用自然语言描述就能生成完整的仿真项目,简直是新手救星!下面分享我的第一个LED闪烁电路仿真实…...
从配置到实战:基于快马生成keil5双环境下的c51与stm32传感器驱动对比项目
在实际嵌入式开发中,经常需要在不同架构的MCU之间切换或协作。最近我在做一个温湿度监测项目,需要在STC89C52(C51架构)和STM32F103C8T6(ARM架构)上分别实现DHT11传感器的驱动。通过这个实战项目,…...
AutoMdxBuilder: 零基础高效制作专业MDX词典的自动化解决方案
AutoMdxBuilder: 零基础高效制作专业MDX词典的自动化解决方案 【免费下载链接】AutoMdxBuilder Automatically make mdx dictionaries 项目地址: https://gitcode.com/gh_mirrors/au/AutoMdxBuilder 当语言教师李老师第三次因为图片路径错误导致MDX词典(一种…...
AI量化投资实战指南:从零开始构建强化学习市场中性策略
AI量化投资实战指南:从零开始构建强化学习市场中性策略 【免费下载链接】qlib Qlib is an AI-oriented Quant investment platform that aims to use AI tech to empower Quant Research, from exploring ideas to implementing productions. Qlib supports diverse…...
3小时掌握拼多多数据采集:Scrapy框架实战指南
3小时掌握拼多多数据采集:Scrapy框架实战指南 【免费下载链接】scrapy-pinduoduo 拼多多爬虫,抓取拼多多热销商品信息和评论 项目地址: https://gitcode.com/gh_mirrors/sc/scrapy-pinduoduo 对于电商数据分析和市场研究从业者而言,获…...
Cursor Pro功能优化工具:提升AI编程体验的开源解决方案
Cursor Pro功能优化工具:提升AI编程体验的开源解决方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…...
OpenClaw健康检查方案:千问3.5-35B-A3B-FP8长期运行维护指南
OpenClaw健康检查方案:千问3.5-35B-A3B-FP8长期运行维护指南 1. 为什么需要健康检查? 去年冬天的一个深夜,我被手机警报惊醒——部署在家庭服务器的OpenClaw千问3.5组合突然停止了响应。检查日志发现是显存泄漏导致进程崩溃,而当…...
50天学习FPGA第41天-PCIe的的介绍及使用
目录 简介 配置过程 简介 XDMA是一种DMA/Bridge Subsystem for PCI Express IP,由Xilinx提供。 XDMA IP核设计使用Xilinx提供的DMASubsystem for PCI Express IP是一个高性能、可配置的适用于PCIE 2.0、PCIE 3.0的SG模式DMA,提供用户可选择的AXI4接口或者AXI4-Stream接口。…...
Jenkins X多集群管理终极指南:跨云平台部署和统一运维
Jenkins X多集群管理终极指南:跨云平台部署和统一运维 【免费下载链接】jx Jenkins X provides automated CICD for Kubernetes with Preview Environments on Pull Requests using Cloud Native pipelines from Tekton 项目地址: https://gitcode.com/gh_mirrors…...
Face3D.ai Pro零基础入门:5分钟从照片到3D人脸,小白也能玩转
Face3D.ai Pro零基础入门:5分钟从照片到3D人脸,小白也能玩转 1. 引言:从照片到3D人脸的魔法 想象一下,用手机随手拍一张自拍,5分钟后就能得到一个可以360度旋转的3D人脸模型。这不是科幻电影里的场景,而是…...
