管理索引

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

查看现有索引

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

列出集合上的所有索引

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

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

db.people.getIndexes()

列出数据库的所有索引

要列出数据库中的所有集合索引,请运行以下命令mongosh:

db.getCollectionNames().forEach(function(collection) {
    indexes = db[collection].getIndexes();
    print("Indexes for " + collection + ":");
    printjson(indexes);
});

列出特定类型的索引

要列出所有数据库中所有集合的特定类型(例如hashedtext)的所有索引,请在 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中的索引,请参阅管理 Compass 中的索引。

修改索引

要修改 MongoDB Shell 中的现有索引,您需要删除并重新创建索引。此规则的例外是 TTL 索引,它可以通过collMod命令与集合标志结合 进行修改index

使用临时索引最大限度地减少性能影响

如果您删除生产中积极使用的索引,您的应用程序可能会导致性能下降。为了确保查询在修改期间仍然可以使用索引,您可以创建一个临时的冗余索引,其中包含与修改后的索引相同的字段。

例子

此示例创建一个新索引并修改该索引以使其 唯一。

  1. 创建一个带有字段siteAnalytics索引的集合url

    运行这个命令:

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

    该命令返回索引的名称:

    url_1
    
  2. url创建包含该字段的临时索引

    运行这个命令:

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

    该命令返回索引的名称:

    url_1_dummyField_1
    

    此临时索引可让您安全地删除原始{ "url": 1 }索引,而不会影响性能。

  3. 删除原来的索引

    运行这个命令:

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

    该命令返回:

    { nIndexesWas: 3, ok: 1 }
    
  4. { "url": 1 }使用unique属性重新创建索引

    运行这个命令:

    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,请运行以下命令:

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

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

查找跨分片不一致的索引

如果分片集合在包含集合块的每个分片上不具有完全相同的索引(包括索引选项),则分片集合的索引不一致。虽然正常操作时不应该出现索引不一致的情况,但是索引不一致的情况还是有可能发生的,比如:

  • 当用户创建具有unique键约束的索引并且一个分片包含具有重复文档的块时。在这种情况下,创建索引操作可能在没有重复项的分片上成功,但在有重复项的分片上失败。
  • 当用户以滚动方式跨分片创建索引时(即手动跨分片逐一构建索引),但未能为关联分片构建索引,或者错误地构建了不同规格的索引。

从 MongoDB 4.4(和 4.2.6)开始,默认情况下,配置服务器主节点会检查分片集合的分片之间的索引不一致情况,并且该命令serverStatus在配置服务器主节点上运行时,会返回 fieldshardedIndexConsistency 字段以报告索引不一致的分片集合的数量。

如果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

    • page_1_score_1上的集合中缺少名为 的索引shardB
    • 指定的索引reviewDt_1在集合的分片中具有不一致的属性,具体来说,expireAfterSeconds 属性不同。

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

您可以:

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

从受影响分片上的集合中删除不正确的索引并重建索引。要重建索引,您可以:

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

Copyright © 上海锦木信息技术有限公司 all right reserved,powered by Gitbook文件修订时间: 2023-09-01 17:10:26

results matching ""

    No results matching ""