Hash和Ascending指数之间的Mongodb性能差异(任何理由不在非有序字段中使用哈希?)

J-R*_*Rou 28 mongodb mongodb-indexes

在mongodb中有多种类型的索引.对于这个问题,我对可用于排序的升序(或降序)索引以及根据文档"主要与分片集群一起使用以支持散列分片键" 的哈希索引感兴趣"()确保"更多均匀分布数据"(来源)

我知道你不能创建一个索引,db.test.ensureIndex( { "key": "hashed", "sortOrder": 1 } )因为你得到一个错误

{
    "createdCollectionAutomatically" : true,
    "numIndexesBefore" : 1,
    "errmsg" : "exception: Currently only single field hashed index supported.",
    "code" : 16763,
    "ok" : 0
}
Run Code Online (Sandbox Code Playgroud)

我的问题:

在指数之间:

  1. db.test.ensureIndex( { "key": 1 } )

  2. db.test.ensureIndex( { "key": "hashed" } )

对于查询db.products.find( { key: "a" } ),哪一个更高性能?是hashed关键O(1)


我是怎么回答这个问题的:

在我知道你不能使用多键索引之前hashed,我创建了一个表单的索引db.test.ensureIndex( { "key": 1, "sortOrder": 1 } ),在创建它时,我想知道散列索引是否比升序索引更高效(散列通常是O(1)).我现在离开了钥匙,因为(正如我上面提到的那样)db.test.ensureIndex( { "key": "hashed", "sortOrder": 1 } )是不允许的.但问题是,关键字搜索的哈希指数更快,我的脑海里仍然存在.

我制作索引的情况是:

我有一个集合,其中包含按键分类的文档的排序列表.

例如 {key: a, sortOrder: 1, ...},{key: a, sortOrder: 2, ...},{key: a, sortOrder: 3, ...},{key: b, sortOrder: 1, ...},{key: b, sortOrder: 2, ...},...

由于我使用了key分类和sortOrder进行分页,因此我总是使用一个值来查询key并使用sortOrderfor文件的顺序.

这意味着我有两个可能的查询:

  • 对于第一页 db.products.find( { key: "a" } ).limit(10).sort({"sortOrder", 1})
  • 而对于其他页面 db.products.find( { key: "a" , sortOrder: { $gt: 10 } } ).limit(10).sort({"sortOrder", 1})

在这个特定的场景中,搜索O(1)密钥和O(log(n))sortOrder是理想的,但这是不允许的.

Wan*_*iar 10

对于查询db.products.find( { key: "a" } ),哪一个更高效?

鉴于该字段key在两种情况下都被索引,复杂性索引搜索本身将非常相似.由于值a将被散列,并存储在索引树中.

如果我们正在寻找总体性能成本,那么散列版本会a在匹配索引树中的值之前产生额外(可忽略的)散列值的成本.另请参见mongo/db/index/hash_access_method.h

此外,散列索引将无法使用索引前缀压缩(WiredTiger).索引前缀压缩对于某些数据集尤其有效,例如具有低基数的数据集(例如,国家/地区),或具有重复值的数据集,例如电话号码,社会保障代码和地理坐标.它对复合索引特别有效,其中第一个字段以第二个字段的所有唯一值重复.

有什么理由不在非有序字段中使用哈希?

通常没有理由对非范围值进行散列.要选择分片键,请考虑值的基数,频率变化率.

散列索引通常用于特定的分片情况.当分片键值单调递增/递减值时,数据分布可能仅进入一个分片.这是散列分片键可以改善写入分布的地方.这是一个很小的权衡,可以大大改善您的分片群集.另请参阅Hashed vs Ranged Sharding.

是否值得在文档中插入随机散列或值,并将其用于分片而不是在_id上生成的散列?

它是否值得,取决于用例.自定义散列值意味着对散列值的任何查询都必须通过自定义散列代码(即应用程序).

利用内置哈希函数的优点是MongoDB在使用散列索引解析查询时自动计算哈希值.因此,应用程序不需要计算哈希值.