Mongodb使用索引进行查询优化

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第80篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关注威赞。谢谢。

前面的文档当中,我们重点介绍了mongodb数据更新update中各种各样的操作符。有兴趣的小伙伴们可以查看本专栏里的相关文章。这篇文章,结合官方文档,探讨一下使用索引进行查询优化。

概述

为集合建立合适的索引,能够有效的减少查询操作时扫描数据的数量 ,从而提高查询效率,简化了mongodb内部查询工作。如原来的某个查询需要进行全表扫描。当集合中有1000条数据时,可能需要逐一扫描这1000条数据,才可以返回查询结果。而当为查询字段添加索引后,通过索引,直接定位到查询结果,可能会极大的减少扫描文档数据的数量。

为读取操作添加索引

当用户建立查询语句,计划通过指定字段或几个字段查询数据时,在指定字段的索引或者几个字段的复合索引能够避免对集合进行全表扫描。

如一个针对表inventory的查询,要求使用字段type作为过滤条件,type是用户指定的一个数值

复制代码
var typeValue = <someUserInput>;
db.inventory.find( {type: typeValue});

为了提高这个针对集合inventory查询的性能,在集合inventory创建一个type字段的索引。使用db.collection.createIndex()方法创建。这个索引,能够避免查询整个集合来返回数据。

复制代码
db.inventory.createIndex({type: 1})

用户可以通过分析执行计划,来确定mongodb是否使用当前索引。

除了提高查询效率以外,索引还可以改善排序操作的效率并能够提过存储空间使用率。

查询操作过滤度

查询操作过滤度表示了查询操作中使用的过滤词排除或者过滤文档的优良程度。查询操作过滤度能够决定该查询是否使用索引。高过滤度查询,能够匹配出更小范围的文档数据。如针对_id字段等等值查询就具备非常高的查询操作过滤度。它几乎可以匹配到唯一的文档数据。相反,低过滤度的查询会匹配集合中更多百分比的数据,几乎不能使用索引。

例如不等操作nin和ne就不是高过滤度查询操作,这两个查询操作经常会匹配到集合中大部分的数据。因此在大多数查询当中,带有nin和ne操作的查询,使用索引查询效率,不会比全表扫描高多少。

而对于正则表达式的查询过滤度,还与正则表达式本身相关。

索引覆盖查询

索引覆盖查询只完全通过索引过滤数据并且使用索引中的字段来返回结果而不需要查询文档数据的查询。同时满足下面三个条件,就可以所该索引覆盖了查询

  • 查询中所有查询字段都是索引的一部分
  • 查询返回字段也包含在该索引当中
  • 查询当中过滤字段没有对null的过滤(如{"field": null}或者{"field": {$eq: null}})。

例如在集合inventory中创建字段type和item的索引

复制代码
db.inventory.createIndex({type: 1, item:1})

该索引覆盖了下面的查询操作。只通过type和item字段过滤数据,只返回item字段

复制代码
db.inventory.find(
    {type:"food", item: /^c/},
    {item:1, _id:0}
)

因为该索引中并不包含_id字段,因此查询返回字段中,需要显示的把_id字段排除。

嵌入式文档索引覆盖查询

同样,索引覆盖查询也适用于嵌入式文档。例如,集合userdata中有下面的数据

复制代码
{ _id:1, user: { login: "tester"}}

为该集合建立索引

复制代码
db.userdata.createIndex({"user.login":1})

该索引可以覆盖下面的查询

复制代码
db.userdata.find( {"user.login": "tester"}, {"user.login": 1, _id: 0})

多键索引覆盖查询

多键索引能够覆盖针对索引中非数组字段的查询。不能覆盖带有数组字段的查询。

索引覆盖查询性能

因为索引当中已经包含了查询中所需要的所有字段和返回字段 ,mongodb可以只通过索引返回查询结果。只通过索引的查询效率,比其他任何索引外查询的效率都要高。因为索引通常保存在内存当中或顺序的保存在磁盘上,而且会比索引依赖的文档小。

索引查询优化限制

  • 地理信息索引不支持索引覆盖查询
  • 多键查询不能覆盖带有数组字段的查询
  • 在分片集中,包含分片key的索引才能支持索引覆盖查询

当然用户可以查看执行计划,确当该查询是否是索引覆盖查询。

相关推荐
科技小花2 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸2 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain2 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希3 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神3 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员3 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java3 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿4 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴4 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存
YOU OU4 小时前
三大范式和E-R图
数据库