# 什么是索引

所有数据库都支持索引,索引文件通过额外占用磁盘空间,提供了一个快速查询记录的方案。查询时先查询索引文件,根据索引文件的指示再去查询真实的数据,在数据量较大时有明显的性能优势。

索引有两个用途:

  1. 在集合中为查询条件的字段建立索引,是保证数据库性能、提升用户体验的重要手段。
  2. 索引可以控制字段中各记录的唯一性。比如某字段被设为唯一索引,则这个字段在整个数据记录集合中的值不会有重复。如果是普通唯一索引,则意味着该字段不能为null。如果是稀疏索引,则代表可以为null,但不为null的值不能重复。

如果您的查询操作包含了过滤条件(包含等值测试和范围过滤)或者是排序功能,或者需要唯一性,则要考虑给集合的相关字段添加索引。通常来说需要为以下方法/属性内用到的字段添加索引where、match、orderBy、sort,还包括clientDB内getTreegetTreePathstartWith属性

如果相关字段没有设为索引,当数据表的记录数量变大后,查询会变慢甚至超时报错。这点尤其需要注意。已经有一些开发者遭遇线上故障。开发时没有配索引,因为数据量小而没有性能问题。上线后数据量越来越大,查询越来越慢,直到超时,引发线上事故。

# 添加索引

# uniCloud web控制台添加

  1. 进入 uniCloud 控制台
  2. 切换到【云数据库】标签页,并选择需要添加索引的集合,进入索引管理 tab 页,如下图。

web控制台添加索引

  1. 添加索引。

添加索引

注意:

  • 索引是支持多字段组合的,所以不是简单的设某个字段为索引。而是需要先给索引起一个name,然后在该索引下配置1个或多个字段。
  • 索引字段的排序,指查询语句中的orderby的顺序。如果实际查询是需要倒叙,那么索引就设为倒叙,这样查询速度才能变快。

# 在db_init.json内配置集合索引

在db_init.json内用如下写法可以给特定集合设置索引(推荐在服务空间初始化时使用)

{
  "opendb-news-article": {
    "data": [],
    "index":[{
      "IndexName": "user_article_", // 索引名称
      "MgoKeySchema": { // 索引规则
          "MgoIndexKeys": [{
              "Name": "user_id", // 索引字段
              "Direction": "1" // 索引方向,1:ASC-升序,-1:DESC-降序,2dsphere:地理位置
          },{
              "Name": "article_id", // 索引字段
              "Direction": "1" // 索引方向,1:ASC-升序,-1:DESC-降序,2dsphere:地理位置
          }],
          "MgoIsUnique": false // 索引是否唯一
      }
    }]
  }
}

# 单字段索引

您可以为查询条件对应的字段创建单字段索引,如果该字段是嵌套字段,可以使用"点表示法" 。例如对如下格式的记录中的color字段进行索引时,可以用style.color表示。

{
  "_id": "",
  "style": {
    "color": ""
  }
}

在设置单字段索引时,可任意指定索引的排序为升序或降序,数据库总能在对索引字段的排序查询中,进行正确的排序。

# 组合索引

组合索引即一个索引包含多个字段。当查询条件使用的字段包含在索引定义的所有字段或前缀字段里时,会命中索引,优化查询性能。

索引前缀即组合索引的字段中定义的前 1 到多个字段,例如对集合 studentsname, age, score 三个字段按顺序定义了组合索引,那么该索引的前缀包含

  • name
  • name, age

能命中索引的查询字段组合包含

  • name
  • name, age
  • name, age, score
{
  "_id": "1",
  "name": "luke",
  "age": 26,
  "score": 80
}

组合索引字段顺序决定组合索引效果

例如定义组合索引分别为 name, ageage, name 是不同的。当组合索引为 name, age 时,其索引前缀为 name, 对字段 name 的查询可以命中 name, age 索引, 而对字段 age 的查询无法命中该索引,因为 age 不属于 name, age 的前缀(反之字段 age 能命中 age, name 索引)。

# 地理位置索引

云数据库目前支持建立平面几何的地理位置索引,使用地理位置查询功能时,必须为地理位置数据的字段建立地理位置索引。

例如对含地理位置字段 point 的集合建立地理位置索引:

{
  "_id": "",
  "point": new db.Geo.Point(50, 50)
}

地理位置索引

# TTL索引

ttl索引用于设置数据过期时间,并在数据过期后进行删除。仅阿里云支持

配置方式如下:

注意

  • 数据删除并非实时,mongoDB会在后台定时进行数据清理
  • 启用ttl索引后仅可添加一个索引字段
  • 仅支持对存储了日期类型(并非时间戳)的字段进行设置ttl索引

# 索引使用注意事项

# 唯一性限制

创建索引时,索引属性选择唯一,即可添加唯一性限制。此限制会要求集合中索引字段对应的值不能重复

例如,某个集合内建立了索引字段 foo,且属性为“唯一”,那么在这个集合内,要求不能存在 foo 字段相同的文档。

注意

假如记录中不存在某个字段,则对索引字段来说其值默认为 null。如果索引有唯一性限制,则不允许存在两个或以上的该字段为空 / 不存在该字段的记录。

针对上述问题,阿里云支持将索引设置为稀疏索引,腾讯云暂不支持稀疏索引。

# 稀疏索引

仅阿里云支持

稀疏索引适用于需要某个字段唯一,但是这个字段又可能为空的场景。以用户表为例,用户可能是通过邮箱注册、也可能是通过手机号注册,所以需要保证邮箱、手机号唯一且允许为空,这时候就可以分别将邮箱、手机号的索引设置为稀疏索引来处理这种场景。注意uni-id内支持多应用用户隔离(同一个手机号、邮箱等可以在不同应用注册账号),手机号、邮箱等都不可设置唯一索引

配置索引为稀疏索引

# 字段大小限制

  • 索引字段的值大小限制不能超过 1024 字节
  • 添加索引时,如果集合中已有文档索引字段内容超过 1024 字节,添加索引时将报错。
  • 已设置索引的字段,如果插入一个文档,文档中该字段内容超过 1024 字节将会报错。

即不要对大段的文字(例如新闻的内容)设置索引

每个英文字母(不分大小写)占一字节的空间,每个中文汉字占两字节的空间。

# 正则表达式

正则查询无法使用索引提升性能。