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字段,没有在该索引的前缀当中。

相关推荐
早日退休!!!15 小时前
大模型推理瓶颈七层分析模型
java·服务器·数据库
大山同学15 小时前
claudecode精炼版-CoreCoder
数据库·人工智能·claude code·corecoder
of Watermelon League15 小时前
5、使用 pgAdmin4 图形化创建和管理 PostgreSQL 数据库
数据库·postgresql
Dontla16 小时前
Python asyncpg库介绍(基于Python asyncio的PostgreSQL数据库驱动)连接池、SQLAlchemy
数据库·python·postgresql
俺不要写代码16 小时前
数据库:DQL
数据库·sql·mysql
zh15702316 小时前
如何编写动态SQL存储过程_使用sp_executesql执行灵活查询
jvm·数据库·python
2401_8242226916 小时前
SQL报表统计数据量巨大_分批统计策略
jvm·数据库·python
俺不要写代码16 小时前
数据库:DCL
数据库
X566116 小时前
mysql如何处理连接数过多报错_调整max_connections参数
jvm·数据库·python
学习3人组16 小时前
OEE(设备综合效率)的标准定义、公式、损失分类、以及在工位触屏/MES里怎么采集和统计
大数据·网络·数据库