Mongodb复合索引

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

在mongodb中,为集合添加单字段索引,能够提高针对单个字段的查询效率。但对于针对多个字段的查询,要怎样提高查询效率呢?例如一个杂货店的老板,想要通过查询商品和剩余数量,来知道是否需要补货。这里我们结合官方文档,整理介绍mongodb的另一个索引类型,复合索引。

定义

复合索引是使用集合当中文档两个或多个字段构成的索引。索引中收集和排序了用户指定的字段,按照用户指定的顺序,依次分组排序。

下图展示了一个复合索引的结构。用户使用userid正序和分数倒序建立的复合索引。在mongodb索引当中,先按照userid字母表顺序正序排列,然后在每一个userid下面,分数按照倒序来排列。

在通用的查询字段上添加索引,能够增加索引覆盖查询的机会。索引覆盖查询是只能够完全使用索引来执行的查询,不需要扫描文档数据来返回结果。

语法

复制代码
db.<collection>.createIndex( {
  <field1>: <sortOrder>,
  <field2>: <sortOrder>,
  ......
  <fieldN>: <sortOrder>,
})

限制

  • 单个复合索引,最多包含32个字段
  • 索引中字段排序影响复合索引的效率。复合索引中包含了依据用户定义的字段顺序所创建的文档引用。
  • 复合索引按照正序或倒序的顺序,保存指定字段值。而这种排序顺序,能够决定查询是否支持索引排序。
  • 复合索引可以包含一个哈希索引字段

复合索引前缀查询

索引前缀查询表示使用索引字段中的前面部分字段来进行的索引查询。mongodb的复合索引,支持这样的前缀查询。

考虑这样的索引

复制代码
{"item": 1, "location": 1, "stock": 1}

该索引当中,包含两个索引前缀

复制代码
{"item": 1}
{"item": 1, "location": 1}

则该索引,能够支持下面的字段组合查询

    • item
    • item + location
    • item + location + stock

mongodb也可以使用这个索引支持item + stock这两个字段的查询。但只有item字段使用了这个索引,stock查询条件无法使用这个索引。因为构建索引时, stock字段跟随在location字段后。索引数据数据中,stock字段值排列在location字段的分组中。索引字段按照建立索引时字段顺序解析。如果一个查询跳过了索引前缀,则无法使用索引。如上述索引,无法支持下面几个字段的查询

    • location
    • stock
    • location + stock

缺少了item字段,这些查询都无法使用该索引。

特殊复合索引

复合索引能够包含不同类型的特殊索引。索引类型的组合方式,能够决定索引匹配文档的方式。

下面的表格展示了包含不同特殊索引的复合索引构建行为。

|------------------|------------------|
| 复合索引构成 | 复合索引行为 |
| 正序索引 倒序索引 | 为包含指定字段的文档建立索引 |
| 正序索引 倒序索引 地理位置索引 | 只能为包含地理位置的文档建立索引 |
| 正序索引 倒序索引 文本索引 | 只能为包含文档字段的文档建立索引 |

应用

构建集合students并插入数据

复制代码
db.students.insertMany([
   {
      "name": "Alice",
      "gpa": 3.6,
      "location": { city: "Sacramento", state: "California" }
   },
   {
      "name": "Bob",
      "gpa": 3.2,
      "location": { city: "Albany", state: "New York" }
   }
])

为name字段和gpa字段添加复合索引。索引中按照name字段的正序排列,gpa字段的倒序排列

复制代码
db.students.createIndex({
    name: 1,
    gpa: -1
})

该索引能够支持针对name和gpa两个字段的查询,也能够支持name字段的查询,因为name字段是该索引的索引前缀。

复制代码
db.students.find({
    name: 'Alice',
    gpa: 3.6
})

db.students.find({
    name: 'Bob'
})

该索引不支持仅包括gpa字段的查询,如

复制代码
db.students.find({ gpa: { $gt: 3.5}})

因为gpa字段,没有在该索引的前缀当中。

相关推荐
python_chai几秒前
从数据汇总到高级分析,SQL 查询进阶实战(下篇)—— 分组、子查询与窗口函数全攻略
数据库·sql·mysql
在努力的前端小白26 分钟前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
未来之窗软件服务28 分钟前
自建知识库,向量数据库 (九)之 量化前奏分词服务——仙盟创梦IDE
数据库·仙盟创梦ide·东方仙盟·自建ai·ai分词
冒泡的肥皂4 小时前
MVCC初学demo(一
数据库·后端·mysql
.Shu.5 小时前
Redis Reactor 模型详解【基本架构、事件循环机制、结合源码详细追踪读写请求从客户端连接到命令执行的完整流程】
数据库·redis·架构
anghost1507 小时前
基于单片机的智能声控窗帘
单片机·嵌入式硬件·mongodb
薛晓刚7 小时前
当MySQL的int不够用了
数据库
SelectDB技术团队8 小时前
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
数据库·数据仓库·数据分析·apache doris·菜鸟技术
星空下的曙光8 小时前
mysql 命令语法操作篇 数据库约束有哪些 怎么使用
数据库·mysql
小楓12018 小时前
MySQL數據庫開發教學(一) 基本架構
数据库·后端·mysql