索引
概述
索引支持 MongoDB 中查询的高效执行。如果没有索引,MongoDB 必须扫描集合中的每个文档才能返回查询结果。如果查询存在适当的索引,MongoDB 会使用该索引来限制必须扫描的文档数量。
虽然索引可以提高查询性能,但添加索引会对写入操作的性能产生负面影响。对于具有高写入读取比率的集合,索引的成本很高,因为每次插入还必须更新任何索引。
场景
如果您的应用程序在相同字段上重复运行查询,您可以在这些字段上创建索引以提高性能。例如,考虑以下场景:
设想 | 指数类型 |
---|---|
人力资源部门经常需要通过员工 ID 查找员工。您可以在员工 ID 字段上创建索引以提高查询性能。 | 单字段索引 |
销售人员经常需要按位置查找客户信息。位置存储在带有 state 、city 和 等字段的嵌入对象中 zipcode 。您可以在整个对象上创建索引 location ,以提高对该对象中任何字段的查询性能。 | 对象上的 单字段索引 |
杂货店经理经常需要按 名称和数量查找库存物品,以确定哪些物品库存不足。item 您可以在和字段上创建单个索引 quantity 以提高查询性能。 | 复合索引 |
细节
- 索引是一种特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。MongoDB 索引使用 B树 数据结构
- 索引条目的排序支持高效的相等匹配和基于范围的查询操作;故可以使用索引中的排序返回排序结果
- MongoDB 在创建集合期间在
_id
字段上创建唯一索引。该索引可防止客户端插入两个具有相同字段值的文档。您不能删除该索引 - 索引的默认名称是索引键和索引中每个键的方向(
1
或-1
)的串联,使用下划线作为分隔符。例如,创建的索引的{ item : 1, quantity: -1 }
名称为item_1_quantity_-1
- 索引一旦创建就无法重命名,只能删掉重新加
创建索引
使用 db.collection.createIndex()
db.collection.createIndex( <key and index type specification>, <options> )
例子
db.collection.createIndex( { name: -1 } )
对于单字段索引,索引键的排序顺序(升序或降序)并不重要,因为 MongoDB 可以沿任一方向遍历索引
获取索引
db.collection.getIndexes()
上个例子会输出:
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { name: -1 }, name: 'name_-1' }
]
指定索引名称
db.<collection>.createIndex(
{ <field>: <value> },
{ name: "<indexName>" }
)
- 索引名称必须是唯一的。使用现有索引的名称创建索引会返回错误。
- 无法重命名现有索引,必须 删除 索引并使用新名称重新创建索引。
如果创建索引时不指定名称,系统将通过将每个索引键字段和值用下划线连接来生成名称。例如:
索引 | 默认名称 |
---|---|
{ score : 1 } | score_1 |
{ content : "text", "description.tags": "text" } | content_text_description.tags_text |
{ category : 1, locale : "2dsphere"} | category_1_locale_2dsphere |
{ "fieldA" : 1, "fieldB" : "hashed", "fieldC" : -1 } | fieldA_1_fieldB_hashed_fieldC_-1 |
删除索引
要删除索引,请使用以下 shell 方法之一:
方法 | 描述 |
---|---|
db.collection.dropIndex() | 从集合中删除特定索引 |
db.collection.dropIndexes() | 从集合或索引数组中删除所有可移动索引(如果指定) |
您可以删除字段上除默认索引之外的任何索引 _id
。要删除 _id
索引,您必须删除整个集合。
如果删除生产中积极使用的索引,则可能会遇到性能下降的情况。在删除索引之前,请考虑 隐藏该索引 以评估删除的潜在影响。
要删除索引,您需要它的名称。要获取集合的所有索引名称,请运行 getIndexes()
db.<collection>.getIndexes()
删除索引后,系统会返回有关操作状态的信息。
输出示例:
...
{ "nIndexesWas" : 3, "ok" : 1 }
...
nIndexesWas
反映了删除索引之前的索引数量
删除单个索引
要删除特定索引,请使用该 dropIndex()
方法并指定索引名称:
db.<collection>.dropIndex("<indexName>")