管理索引
本页介绍如何管理现有索引。有关创建索引的说明,请参阅特定索引类型页面。
查看现有索引
以下部分提供了查看集合或整个数据库上现有索引的方法。
列出集合上的所有索引
要返回集合上所有索引的列表,请使用 db.collection.getIndexes()
方法或适用于您的驾驶员的类似方法。
例如,要查看 people
集合上的所有索引,请运行以下命令:
db.people.getIndexes()
列出数据库的所有索引
要列出数据库中的所有集合索引,可以在mongosh
中使用以下操作:
db.getCollectionNames().forEach(function(collection) { indexes = db[collection].getIndexes(); print("Indexes for " + collection + ":"); printjson(indexes); });
从版本3.0开始, MongoDB 不建议直接访问system.indexes
集合,该集合以前用于列出数据库中的所有索引。
列出特定类型的索引
要列出特定类型的所有索引(例如 对于所有数据库中的所有集合,您可以在mongosh
中使用以下操作:
// The following finds all hashed indexes db.adminCommand("listDatabases").databases.forEach(function(d){ let mdb = db.getSiblingDB(d.name); mdb.getCollectionInfos({ type: "collection" }).forEach(function(c){ let currentCollection = mdb.getCollection(c.name); currentCollection.getIndexes().forEach(function(idx){ let idxValues = Object.values(Object.assign({}, idx.key)); if (idxValues.includes("hashed")) { print("Hashed index: " + idx.name + " on " + d.name + "." + c.name); printjson(idx); }; }); }); });
删除索引
提示
在删除索引之前将其隐藏
删除生产中频繁使用的索引可能导致应用程序性能下降。在删除索引之前,您可以通过隐藏索引来评估删除的潜在影响。
隐藏的索引不能支持查询。如果隐藏索引后发现严重的负面性能影响,请考虑保持该索引并取消隐藏,以便查询可继续使用它。
在 MongoDB Shell 中删除索引时,您可以:
删除特定索引。
从集合中删除所有索引。
删除特定索引
要删除索引,请使用db.collection.dropIndex()
方法。
例如,以下操作删除accounts
集合中tax-id
字段的升序索引:
db.accounts.dropIndex( { "tax-id": 1 } )
该操作返回一个包含操作状态的文档:
{ "nIndexesWas" : 3, "ok" : 1 }
其中nIndexesWas
的值反映了删除该索引之前的索引数量。
对于文本索引,请将索引名称传递给db.collection.dropIndex()
方法。 有关详细信息,请参阅使用索引名称删除text
索引。
注意
db.collection.dropIndexes()
可以接受索引名称数组。
db.collection.dropIndexes()
可以停止正在进行的索引构建。 有关更多信息,请参阅中止正在进行的索引构建。
删除所有索引
您还可以使用db.collection.dropIndexes()
从集合中删除除 _id 索引之外的 所有 索引。
例如,以下命令会从accounts
集合中删除所有索引:
db.accounts.dropIndexes()
这些shell助手提供dropIndexes
数据库命令的包装器。 您的客户端库可能有用于这些操作的不同或附加接口。
要从MongoDB Compass中的集合中删除索引,请执行以下操作:
导航到包含目标索引的集合。
单击 Indexes 标签页。
在目标索引的Drop列中,单击垃圾桶图标。
修改索引
使用临时索引尽量减少对性能的影响
如果您移除生产中频繁使用的索引,则可能导致应用程序性能下降。要确保查询在修改期间仍可使用索引,您可以创建临时的冗余索引,使其中包含与修改后的索引相同的字段。
例子
此示例创建了一个新索引,并修改该索引使其成为唯一索引。
创建包含 字段的临时索引<a class=\" \" href=\" \" title=\" \"><svg xmlns=\" \" width=\" \" height=\" \" fill=\" \" viewbox=\" \"url
class=\" \" role=\" \" aria-label=\" \"><path fill=\" \" d=\" \"> <path fill=\" \" d=\" \">
运行以下命令:
db.siteAnalytics.createIndex( { "url": 1, "dummyField": 1 } )
此命令将返回索引的名称:
url_1_dummyField_1
该临时索引可让您在不影响性能的情况下安全删除原始 { "url":
1 }
索引。
使用{ "url": 1 }
属性重新创建 索引<a class=\" \" href=\" \" title=\" \"><svg xmlns=\" \" width=\" \" height=\" \" fill=\" \" viewbox=\" \" class=\" \" role=\" \" aria-label=\" \"><path fill=\" \" d=\" \"> <path fill=\" \" d=\" \">unique
运行以下命令:
db.siteAnalytics.createIndex( { "url": 1 }, { "unique": true } )
此命令将返回索引的名称:
url_1
系统会重新创建 url_1
索引,您可删除临时索引,而不会影响性能。对 url
字段的查询可使用这个新的唯一索引。
查找分片中不一致的索引
如果分片集合在包含集合数据段的每个分片上不具有完全相同的索引(包括索引选项),则分片集合的索引不一致。正常操作时不应出现索引不一致的情况,但索引不一致的情况仍有可能出现,例如:
当用户使用
unique
键约束创建索引,且一个分片包含具有重复文档的数据段时。在此类情况下,创建索引操作可能会对没有重复项的分片成功完成,而对有重复项的分片失败。当用户以滚动方式跨分片创建索引(即在分片中逐个手动构建索引),但未能为关联分片构建索引或错误地构建了具有不同规范的索引。
默认情况下,配置服务器主节点会检查分片集合的分片中是否存在索引不一致,在配置服务器主节点上运行命令 serverStatus
时会返回字段 shardedIndexConsistency
以报告存在索引不一致的分片集合数量。
如果 shardedIndexConsistency
报告了索引不一致,则可为分片集合运行以下管道,直到找到这些不一致。
定义以下聚合管道:
const pipeline = [ // Get indexes and the shards that they belong to. {$indexStats: {}}, // Attach a list of all shards which reported indexes to each document from $indexStats. {$group: {_id: null, indexDoc: {$push: "$$ROOT"}, allShards: {$addToSet: "$shard"}}}, // Unwind the generated array back into an array of index documents. {$unwind: "$indexDoc"}, // Group by index name. { $group: { "_id": "$indexDoc.name", "shards": {$push: "$indexDoc.shard"}, // Convert each index specification into an array of its properties // that can be compared using set operators. "specs": {$push: {$objectToArray: {$ifNull: ["$indexDoc.spec", {}]}}}, "allShards": {$first: "$allShards"} } }, // Compute which indexes are not present on all targeted shards and // which index specification properties aren't the same across all shards. { $project: { missingFromShards: {$setDifference: ["$allShards", "$shards"]}, inconsistentProperties: { $setDifference: [ {$reduce: { input: "$specs", initialValue: {$arrayElemAt: ["$specs", 0]}, in: {$setUnion: ["$$value", "$$this"]}}}, {$reduce: { input: "$specs", initialValue: {$arrayElemAt: ["$specs", 0]}, in: {$setIntersection: ["$$value", "$$this"]}}} ] } } }, // Only return output that indicates an index was inconsistent, i.e. either a shard was missing // an index or a property on at least one shard was not the same on all others. { $match: { $expr: {$or: [ {$gt: [{$size: "$missingFromShards"}, 0]}, {$gt: [{$size: "$inconsistentProperties"}, 0]}, ] } } }, // Output relevant fields. {$project: {_id: 0, indexName: "$$ROOT._id", inconsistentProperties: 1, missingFromShards: 1}} ]; 为待测试的分片集合运行该聚合管道。例如,测试分片集合
test.reviews
在其关联的分片之间是否存在不一致索引:db.getSiblingDB("test").reviews.aggregate(pipeline) 如果集合存在不一致索引,则该集合的聚合会返回有关不一致索引的详情:
{ "missingFromShards" : [ "shardB" ], "inconsistentProperties" : [ ], "indexName" : "page_1_score_1" } { "missingFromShards" : [ ], "inconsistentProperties" : [ { "k" : "expireAfterSeconds", "v" : 60 }, { "k" : "expireAfterSeconds", "v" : 600 } ], "indexName" : "reviewDt_1" } 返回文档表明分片集合
test.reviews
存在两个不一致:在
shardB
上该集合缺少名为page_1_score_1
的索引。名为
reviewDt_1
的索引在该集合的分片之间存在不一致的属性,具体是expireAfterSeconds
属性不同。
- 要解决特定分片上的集合中缺少索引而产生的不一致问题,
您可以执行以下任一操作:
在受影响的分片上为该集合执行滚动索引构建。
-或-
从
mongos
实例发出索引构建db.collection.createIndex()
。此操作仅会对缺少该索引的分片构建集合的索引。
- 要解决分片之间索引属性不同的问题,
从受影响的分片上的集合中删除不正确的索引,然后重新生成索引。要重建索引,您可以采取以下任一操作:
在受影响的分片上为该集合执行滚动索引构建。
-或-
从
mongos
实例发出索引构建db.collection.createIndex()
。此操作仅会对缺少该索引的分片构建集合的索引。
如果不一致涉及
expireAfterSeconds
属性,则可运行collMod
命令来更新秒数,无需删除并重新构建索引。