【问题标题】:What is the _id_hashed index for in mongoDB?mongoDB 中的 _id_hashed 索引是什么?
【发布时间】:2013-09-07 09:58:54
【问题描述】:

我通过散列 _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

【问题讨论】:

    标签: mongodb mongodb-indexes


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      当您执行 sh.shardCollection( 'db.collection', { _id:"hashed" } ) 时,您告诉它您想使用 _id 的哈希作为分片键,这需要_id 上的哈希索引。

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

      【讨论】:

      • 是的,我在 mongoDB 手册上找到了。令我困惑的是:这个散列索引是干什么用的?你能解释更多关于 mongoDB 将如何利用这个索引的信息吗?谢谢。
      • 如果你想为你的分片键使用 _id 值的哈希值,mongoDB 将需要一个分片键上的索引(以便快速查找范围),因此它需要一个 _id 哈希值的索引。 (除了对实际 _id 值的索引,这是强制性的)。
      • 为什么 mongoDB 需要在散列键索引中查找范围?何时将块迁移到其他分片?
      • 它不是专门用于范围(我应该使用更通用的搜索示例),而是用于任何查找。
      • 我只需要在_id字段上查询。我检查了执行计划(参见我的原始帖子),在这种情况下似乎没有使用 _id_hashed 索引。何时以及如何使用索引?
      【解决方案3】:

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

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

      所以想象一下_id 字段,它是一个不断增加的范围,所有新的_ids 将在之后,这意味着您总是在集群的末尾写入,从而创建一个热点。

      至于阅读,您通常只阅读最新的文档,这意味着_id 键的上限是唯一用于在集群的上限,而集群的其余部分则闲置在那里。

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

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

      【讨论】:

      • 对于热点的事情,这就是我使用散列的_id字段作为分片键的原因。
      • @zach 等一下你的问题是什么?
      • 也许你误解了我的问题。我了解热点问题,这就是为什么我使用散列 id 字段作为分片键,而不仅仅是 _id 字段。换句话说,如果我只是使用 _id 字段作为分片键,情况很简单:我将只有一个 _id 索引。 mongoDB 使用此索引来搜索 _id 字段上的查询。当我使用散列 _id 作为分片键时,MongoDB 生成另一个 _id_hashed 索引,我不明白 mongoDB 何时以及如何使用该索引?
      • @zach MongoDB 将使用该索引而不是 _id 索引,因此它实际上将完全使用散列索引,即 _id_hashed 是散列索引
      • 恐怕不正确。 “indexBounds”:{“start”:{“_id”:“spiderman_task_captainStatus_30491467_2387600”},“end”:{“_id”:“spiderman_task_captainStatus_30491467_2387600”}},
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2016-08-07
        • 1970-01-01
        • 2016-02-28
        • 2013-02-08
        • 2011-02-26
        • 2011-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多