MongoDB 中的索引

160 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

我们知道索引支持在 MongoDB 中有效地执行查询。如果没有索引,MongoDB 就会执行集合扫描,选择那些与查询语句匹配的文档。如果一个查询存在适当的索引,MongoDB 可以使用该索引来限制它必须检查的文档数量。

MongoDB 提供了许多不同的索引类型来支持特定类型的数据和查询,比如单字段索引复合索引多键索引文本索引地理空间索引Hashed 索引等等

多键索引

多键索引支持对数组字段的高效查询。如果想对文档中的数组值字段或者子文档进行检索,此时就可以为数组中的每个元素创建一个索引键,即多键索引。接下来我们就一起来学习多键索引。

多键索引创建的语法

  • 使用 db.collection.createIndex() 方法创建一个多键索引,格式如下:

    db.collection.createIndex({<field>:< 1 or -1>})
    

    ✨ 说明:MongoDB 自动创建一个多值索引,如果索引字段是一个数组,不需要显示地制定多键类型。

索引数组字段

  • 给集合 student 中的 hobby 字段添加一个多键索引。

    db.student.createIndex({"hobby":1})
    

    ✨ 说明:由于 hobby 字段包含一个数组,故 hobby 字段的索引是多键的。

  • 查看创建的索引。

    db.student.getIndexes()
    
  • 查询 hobby 字段中包含**"乒乓球"**的文档信息。

    db.student.find({hobby:"乒乓球"}).pretty()
    

    ✨ 说明:如果大家想验证查询时是否使用了索引,可以使用 explain() 方法,即 db.student.find({hobby:"乒乓球"}).pretty().explain()

索引子文档字段

  • 给集合 student 中文档的 city 和 district 字段创建索引。

    db.student.createIndex({"address.city":1,"address.district":1})
    
  • 查看创建的索引。

    db.student.getIndexes()
    
  • 查询 city 为  "Chongqing"  的文档信息。

    db.student.find({"address.city":"Chongqing"}).pretty()
    

文本索引

MongoDB 也提供了文本索引以支持对字符串的文本搜索查询。文本索引可以包含任何值为字符串或字符串元素数组的字段。注意不同版本,文本索引的使用会有所区别,这里是以 4.4 版本为例。

a. 给集合 student 中 name 字段创建文本索引。

db.student.createIndex({name:"text"})

✨ 说明:这里的 text 是固定值,表示文本索引。这里需要注意,一个集合中最多可以有一个 text 索引

b. 查询创建的索引。

db.student.getIndexes()

c. 查询名称为杨过的文档信息。

db.student.find({name:"杨过"}).pretty()

✨ 说明:也可以使用 db.books.find({$text:{$search:"杨过"}}) 进行查询。

🌟 补充:在多个字段上创建文本索引时,还可以使用通配符说明符($**)。通过通配符文本索引,MongoDB 为集合中每个文档包含字符串数据的每个字段建立索引。比如:

db.student.createIndex({"$**":"text"})

索引限制条件

从关系型数据库,我们知道索引不是创建的越多越好。同样在 MongoDB 中也一样有限制,接下来我们就一起来看看都有哪些限制条件。

a. 索引键限制

⚠️ 注意:在 4.2 版本有变更。从 4.2 版本开始,MongoDB 对于将 fCV(featureCompatibilityVersion 设置成 4.2 或更高的环境去除了此索引键限制

b. 每个集合中的索引个数:单个集合内不能超过 64 个索引。

c. 索引名称长度

⚠️ 注意:在 4.2 版本有变更。从 4.2 版本开始,MongoDB 对于将 fCV(featureCompatibilityVersion 设置成 4.2 或更高的环境去除了此索引名称长度限制

d. 复合索引的字段数量:复合索引中所包含的字段不能超过 32 个。

e. 查询不能同时使用文本索引和地理空间索引:不能将需要特殊文本索引的 $text 查询与需要不同类型特殊索引的查询运算符组合在一起。

f. 额外开销:每个索引占据一定的存储空间,在执行插入、更新和删除操作时也需要对索引进行操作。所以,如果很少对集合进行读取操作,建议不使用索引。

g. 内存(RAM) 使用

  • 由于索引是存储在内存(RAM)中,故应该确保索引的大小不超过内存的限制。
  • 如果索引的大小大于内存的限制,MongoDB 会删除一些索引,会导致性能下降。