Docs 菜单

Docs 主页开发应用程序MongoDB Manual

管理索引

在此页面上

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

本页介绍如何管理现有索引。有关创建索引的说明,请参阅特定索引类型页面。

提示

在删除索引之前将其隐藏

删除生产中频繁使用的索引可能导致应用程序性能下降。在删除索引之前,您可以通过隐藏索引来评估删除的潜在影响。

隐藏的索引不能支持查询。如果隐藏索引后发现严重的负面性能影响,请考虑保持该索引并取消隐藏,以便查询可继续使用它。

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

要了解如何在 MongoDB Compass 中删除索引,请参阅 在 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 }
]

如果分片集合在包含集合数据段的每个分片上不具有完全相同的索引(包括索引选项),则分片集合的索引不一致。正常操作时不应出现索引不一致的情况,但索引不一致的情况仍有可能出现,例如:

默认,配置服务器主节点会检查分片collection之间的索引是否不一致,而在配置服务器主节点上运行serverStatus命令时,会返回shardedIndexConsistency字段以报告分片collection的数量索引不一致。

如果 shardedIndexConsistency 报告了索引不一致,则可为分片集合运行以下管道,直到找到这些不一致。

注意

以下管道适用于 MongoDB 4.2.4 及以上版本。

  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. shardB 上该集合缺少名为 page_1_score_1 的索引。

    2. 名为 reviewDt_1 的索引在该集合的分片之间存在不一致的属性,具体是 expireAfterSeconds 属性不同。

要解决特定分片上的集合中缺少索引而产生的不一致问题,

您可以执行以下任一操作:

要解决分片之间索引属性不同的问题,

从受影响的分片上的集合中删除不正确的索引,然后重新生成索引。要重建索引,您可以采取以下任一操作:

如果不一致涉及 expireAfterSeconds 属性,则可运行 collMod 命令来更新秒数,无需删除并重新构建索引。

← 在分片集群上滚动构建索引