说一说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…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...