文档菜单
文档首页
/
MongoDB 手册
/

管理索引

本页内容

  • 查看现有索引
  • 删除索引
  • 修改索引
  • 跨分片查找不一致的索引

此页面展示了如何管理现有索引。有关创建索引的说明,请参阅特定索引类型页面。

以下部分提供了查看集合或整个数据库上现有索引的方法。

要返回集合上所有索引的列表,请使用db.collection.getIndexes() 方法或您驱动程序的类似方法方法.

例如,要查看 people 集合上的所有索引,请运行以下命令

db.people.getIndexes()

要列出数据库中所有集合的索引,请在 mongosh:

db.getCollectionNames().forEach(function(collection) {
indexes = db[collection].getIndexes();
print("Indexes for " + collection + ":");
printjson(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 Compass中查看集合上所有索引的列表,MongoDB Compass,在左侧面板中点击目标集合,并选择索引选项卡。

View indexes on a collection in Compass

关于此选项卡上显示的信息的详细信息,请参阅Compass 文档。

提示

在删除之前隐藏索引

如果您在生产环境中删除了正在积极使用的索引,您的应用程序可能会遭受性能下降。在您删除索引之前,您可以隐藏索引来评估删除的影响。

隐藏的索引不用于支持查询。如果您隐藏了一个索引并观察到显著的负面影响,请考虑保留并取消隐藏索引,以便查询可以继续使用它。

要了解如何删除现有索引,请参阅删除索引。

要了解如何删除MongoDB Compass中的索引,请参阅在 Compass 中管理索引。

要在MongoDB Shell中修改现有的索引,您需要先删除再重新创建该索引。例外情况是TTL索引,可以通过与collMod命令结合使用index集合标志来修改。

要修改现有的索引MongoDB Compass,您需要删除并重新创建该索引。

如果您删除了在生产环境中正在使用的索引,您的应用程序可能会出现性能下降。为了确保在修改期间查询仍可以使用索引,您可以创建一个临时、冗余的索引,该索引包含与修改的索引相同的字段。

此示例创建了一个新的索引,并将其修改为唯一

1

运行以下命令

db.siteAnalytics.createIndex( { "url": 1 } )

命令返回索引名称

url_1
2

运行以下命令

db.siteAnalytics.createIndex( { "url": 1, "dummyField": 1 } )

命令返回索引名称

url_1_dummyField_1

这个临时索引可以安全地删除原始的 { "url": 1 } 索引,而不会影响性能。

3

运行以下命令

db.siteAnalytics.dropIndex( { "url_1" } )

命令返回

{ nIndexesWas: 3, ok: 1 }
4

运行以下命令

db.siteAnalytics.createIndex( { "url": 1 }, { "unique": true } )

命令返回索引名称

url_1

重新创建了 url_1 指数,您可以删除临时索引而不会影响性能。对 url 字段的查询可以使用新的唯一索引。

5

运行以下命令

db.siteAnalytics.dropIndex( { "url_1_dummyField_1" } )

命令返回

{ nIndexesWas: 3, ok: 1 }
6

要查看 siteAnalytics 集合上的索引,请运行此命令

db.siteAnalytics.getIndexes()

该命令返回这些索引,表明 url_1 指数现在是唯一的

[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { url: 1 }, name: 'url_1', unique: true }
]

如果分片集合在每个包含集合数据块的分片上没有完全相同的索引(包括索引选项),则该分片集合存在不一致的索引。虽然不一致的索引不应该在正常操作期间发生,但可能会发生不一致的索引,例如

  • 当用户使用具有唯一键约束创建索引,并且一个分片包含具有重复文档的数据块时。在这种情况下,创建索引操作可能在没有重复项的分片上成功,但在有重复项的分片上失败。

  • 当用户以滚动方式(即逐个分片手动构建索引)创建跨分片的索引,但无法为相关分片构建索引或错误地使用不同的规范构建索引时。

默认情况下,配置服务器主节点会检查分片集合跨分片的不一致索引,并且当在配置服务器主节点上运行serverStatus命令时,返回字段shardedIndexConsistency以报告具有索引不一致的分片集合数量。

如果shardedIndexConsistency报告任何索引不一致,您可以运行以下管道直到找到不一致为止。

  1. 定义以下聚合管道:

    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}}
    ];
  2. 运行聚合管道以测试分片集合。例如,要测试分片集合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存在两个不一致

    1. 名为page_1_score_1的索引在shardB上的集合中缺失。

    2. 名为reviewDt_1的索引在其集合的分片之间具有不一致的属性,具体来说,expireAfterSeconds属性不同。

要解决特定分片上的索引缺失的不一致性问题

您可以

  • 对受影响的分片(s)上的集合执行滚动索引构建

    -或-

  • db.collection.createIndex() 命令在 mongos 实例中创建索引。此操作仅会在缺少索引的分片上构建集合的索引。

为了解决分片间索引属性不同的问题,

从受影响的分片上的集合中删除错误的索引并重新构建索引。要重新构建索引,您可以

或者,如果不一致性是 expireAfterSeconds 属性导致的,您可以运行 collMod 命令来更新秒数,而不是删除和重新构建索引。

返回

在分片集群中创建