07-添加索引
22.2.1 添加索引
在MongoDB中,可根据集合中的字段创建索引,以提高文档查找速度。在MongoDB中添加索引时,将在后台创建一个特殊的数据结构(其中存储了集合的一小部分数据),再对其进行优化以提高查找特定文档的速度。
例如,根据_id字段创建索引时,将创建一个包含_id值的有序数组。创建这种索引有下面这些好处。
- 按_id查找文档时,可在这个有序索引中搜索,从而更快地找到文档。
- 假设您希望返回的文档按_id排序,这种排序已在索引中完成,因此不需要再这样做,MongoDB只需按_id在索引中出现的顺序返回文档。
- 现在假设您希望文档按_id排序,并返回第10~20个文档。为此,只需截取索引中的这部分_id,再根据_id查找文档。
- 最重要的是,如果您要获取有序的_id值列表,MongoDB根本不需要读取文档,而只需直接返回索引中的值。
然而,别忘了获得这些好处是要付出代价的。下面是索引的一些开销。
- 索引需要占用磁盘和内存空间。
- 插入和更新文档时,索引将占用处理时间。这意味着集合包含大量索引时,将影响数据库写入操作的性能。
- 集合越大,索引在资源和性能方面的开销越高。在超大集合中,甚至都不适合创建索引。
在集合中,可根据设计需求创建多种索引。表22.1列出了各种索引类型。
| 类型 | 描述 | | :----- | :----- | :----- | :----- | | 默认的_id索引 | 所有MongoDB集合默认都包含基于_id的索引。如果应用程序没有给文档指定_id值,MongoDB服务器将为文档创建包含ObjectID值的_id字段。_id索引是唯一的,禁止客户端插入两个_id值相同的文档 | | 单字段索引 | 最简单的索引是单字段索引。这种索引类似于_id索引,但是根据指定的字段创建的。这种索引可按升序或降序排列,且不要求指定字段的值是唯一的。例如:{name: 1} | | 复合索引 | 这种索引基于多个字段,它首先根据第一个字段排序,再根据第二个字段排序,依此类推。各个字段的排序方向可以不同,例如,可根据一个字段升序排列,并根据另一个字段降序排列,如{name: 1, value: -1} | | 多键索引 | 基于数组字段创建索引时,将为数组中的每个元素创建一个索引项。这使得根据索引包含的值查找对象时速度更快。例如,如果有一个myObjs对象数组,其中每个对象都有score字段,将创建基于score字段的索引:{myObjs.score: 1} | | 地理空间索引 | MongoDB支持创建基于二维坐标或二维球面坐标的地理空间索引。这意味着您能更有效地存储和检索引用地理位置的数据。例如:{"locs":"2d"} | | 全文索引 | MongoDB还支持创建全文索引,这让使得根据单词查找字符串元素的速度更快。全文索引不会存储the、a和is等单词。例如:{comment: "text"} | | 散列索引 | 使用基于散列的分片时,MongoDB支持创建散列索引,其中值包含存储在特定服务器中的散列值,这可避免在其他服务器中存储不相关散列值的开销。例如:{key: "hashed"} |
创建索引时,还可指定一些特殊属性(如表22.2所示),这些属性告诉MongoDB该如何处理索引。
| 属性 | 描述 | | :----- | :----- | :----- | :----- | | background | 布尔值。如果为true,MongoDB将在后台创建索引,这使得在索引创建期间允许对集合执行写入操作;如果为false,将在索引创建完毕前禁止对集合执行写入操作 | | unique | 禁止索引包含同一个字段值多次。因此,添加文档时,如果包含的字段值已出现在索引中,MongoDB将禁止添加该文档 | | sparse | 仅当文档包含索引字段时,索引中才会有其条目。这种索引忽略没有索引字段的文档 | | TTL | 存活时间(Time To Live,TTL)索引只让文档在索引中存在指定的时间。例如,这适用于特定时间后需要清除的日志条目和事件数据。这种索引记录插入时间,并在条目过期后将其删除 | | dropDups | 布尔值。如果为true且unique为true,将把索引字段与既有文档相同的所有文档删除 | | name | 可给索引指定名称,以便在其他命令中引用它 |
可结合使用属性unique和sparse,让索引拒绝索引字段为重复值的文档,并拒绝不包含索引字段的文档。
使用MongoDB shell和大部分MongoDB驱动程序都可创建索引。要使用MongoDB shell来创建索引,可使用方法ensureIndex(index, properties)。例如,下面的代码创建一个名为myIndex的唯一索引,该索引基于字段name(升序)和number(降序):
db.myCollection.ensureIndex({name:1, number: -1},
{background:true, unique:true , name: "myIndex"})