3

我通过散列 _id 对我的 mongoDB 集群进行了分片。我检查了索引大小,有一个 _id_hashed 索引占用了很多空间:

   "indexSizes" : {
           "_id_" : 14060169088,
           "_id_hashed" : 9549780576
    },

mongoDB 手册说,如果您对集合进行分片,则会在分片键上创建一个索引。我想这就是 _id_hashed 索引存在的原因。

我的问题是:如果我只通过 _id 字段查询文档,那么 _id_hashed 索引是什么?我可以删除它吗?因为它占用太多空间。

ps:似乎mongoDB在查询时使用_id索引,而不是_id_hashed索引。查询的执行计划:

   "clusteredType" : "ParallelSort",
    "shards" : {
            "rs1/192.168.62.168:27017,192.168.62.181:27017" : [
                    {
                            "cursor" : "BtreeCursor _id_",
                            "isMultiKey" : false,
                            "n" : 0,
                            "nscannedObjects" : 0,
                            "nscanned" : 1,
                            "nscannedObjectsAllPlans" : 0,
                            "nscannedAllPlans" : 1,
                            "scanAndOrder" : false,
                            "indexOnly" : false,
                            "nYields" : 0,
                            "nChunkSkips" : 0,
                            "millis" : 0,
                            "indexBounds" : {
                                    "start" : {
                                            "_id" : "spiderman_task_captainStatus_30491467_2387600"
                                    },
                                    "end" : {
                                            "_id" : "spiderman_task_captainStatus_30491467_2387600"
                                    }
                            },
                            "server" : "localhost:27017"
                    }
            ]
    },
    "cursor" : "BtreeCursor _id_",
    "n" : 0,
    "nChunkSkips" : 0,
    "nYields" : 0,
    "nscanned" : 1,
    "nscannedAllPlans" : 1,
    "nscannedObjects" : 0,
    "nscannedObjectsAllPlans" : 0,
    "millisShardTotal" : 0,
    "millisShardAvg" : 0,
    "numQueries" : 1,
    "numShards" : 1,
    "indexBounds" : {
            "start" : {
                    "_id" : "spiderman_task_captainStatus_30491467_2387600"
            },
            "end" : {
                    "_id" : "spiderman_task_captainStatus_30491467_2387600"
            }
    },
    "millis" : 574
4

4 回答 4

3

MongoDB 使用基于范围的分片方法。如果您选择使用基于散列的分片,您必须在分片键上有一个散列索引并且不能删除它,因为它将用于确定用于任何后续查询的分片(请注意,有一个开放票允许您删除_id 索引一旦散列索引被允许是唯一的 SERVER-8031 )。

至于为什么查询似乎使用 _id 索引而不是 _id_hashed 索引 - 我进行了一些测试,我认为优化器正在选择 _id 索引,因为它是唯一的并且会产生更有效的计划。如果您对另一个具有预先存在的唯一索引的键进行分片,您会看到类似的行为。

于 2013-09-04T15:57:21.957 回答
0

如果您在散列 _id 上进行分片,那么这就是创建的索引类型。

当你这样做时,sh.shardCollection( 'db.collection', { _id:"hashed" } )你告诉它你想使用 _id 的哈希作为分片键,这需要_id.

所以,不,你不能放弃它。

于 2013-09-04T03:36:36.767 回答
0

该文档详细介绍了哈希索引的确切含义,这让我感到困惑,您是如何阅读文档但不知道哈希索引的用途的。

该索引主要是为了阻止分片键中的热点,这些热点可能不均匀地分布在它们的读/写上。

所以想象一下这个_id领域,它是一个不断扩大的范围,所有新_id的s都将在之后,这意味着你总是在你的集群的末尾写,创造一个热点。

至于阅读,您只阅读最新文档可能很常见,因此这意味着_id密钥的上限是唯一用于在集群的上限范围内形成读写热点的密钥,而您的集群的其余部分只是闲置在那里。

哈希索引采用这个坏的分片键并以这样的方式对其进行哈希处理,这意味着它不会永远增加,而是会创建一个均匀分布的数据集用于读取和写入,希望整个集合都可以用于操作。

我强烈建议您不要删除它。

于 2013-09-04T07:24:21.230 回答
0

分片集合需要散列索引,更准确地说,分片平衡器需要散列索引直接根据散列值查找文档,正常的查询操作不需要索引是散列索引,即使在共享集合上也是如此。

于 2019-09-05T04:27:36.853 回答