MongoDB 哈希索引

Posted MongoDB

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB 哈希索引相关的知识,希望对你有一定的参考价值。

哈希索引

  • 哈希函数

  • 创建一个哈希索引

  • 注意事项

哈希索引使用字段的哈希值构建索引。

MongoDB分片中也支持哈希分片键。在分片集群中,如果数据记录的某字段使用哈希索引,在分片中仅需为该字段创建哈希分片键即可。

 在分片集群中对一个collection进行哈希分片会导致更多的数据随机分布 。

哈希函数

哈希索引使用一个散列函数计算索引字段的哈希值。对于是嵌套文档的字段,哈希函数将计算整个嵌套文档的哈希值。在多键索引中不能使用哈希索引。

提示:

在执行使用到哈希索引的查询时自动计算哈希值,不需要应用程序自己计算查询字段的哈希值。

从MongoDB 4.0开始,mongo shell 提供 convertShardKeyToHashed() 函数。该函数可以用来查看一个键的哈希值。

创建哈希索引

对记录的指定字段创建哈希索引,命令如下:

db.collection.createIndex( { _id: "hashed" } )

注意事项

MongoDB支持对任何单一字段创建哈希索引,对于是嵌套文档的字段,哈希函数将计算整个嵌套文档的散列值,(例如:"a":{"b":"xxx","c":"xxx"},对于a字段创建哈希索引,哈希函数将计算整个{"b":"xxx","c":"xxx"}的散列值),但不支持在多键索引中使用哈希索引(例入:不可对属性是数组的字段创建哈希索引)。

我们不可在复合索引中使用哈希索引,也不可在哈希索引上指定唯一约束。但我们可以对同一字段创建一个哈希索引和非哈希索引(例入:升序/降序类索引):在进行范围查询时,MongoDB将自动选择升序/降序索引。

2^53^ Limit 2^53^限制

注意

MongoDB哈希索引在计算散列之前将浮点数截断为64位整数。例如:对于哈希索引属性,数据内容为2.32.2, 和 2.9的记录对应的哈希列值是相同的。为了避免这种冲突,不建议对无法可靠转换成64位整数的浮点数属性字段创建哈希索引。MongoDB不支持对大于2^53^的浮点值使用哈希索引。

To see what the hashed value would be for a key, see convertShardKeyToHashed(). 查看键对应的哈希值请查看convertShardKeyToHashed()

PowerPC and 2^63^ PowerPC 和 2^63^

PowerPC和其他处理器中,MongoDB 4.2都保证可以计算64位(8字节)双精度浮点数(-1.79E+308 ~ +1.79E+308)的哈希值。

虽然大于2^53^的浮点数属性是无法配置的,但是客户端仍然可以插入索引字段值是2^63^的文档。

查询部署的MongoDB实例中所有数据库中所有collection中的哈希索引,可以在mongo shell中使用如下命令:

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 " + idx.ns);
printjson(idx);
};
});
});
});

检查某个collection的索引字段数据内容是2^63^位的值,使用如下命令:

  • 如果一个collection中的索引字段数据内容仅是数值,不存在任何文档:

     // substitute the actual collection name for <collection>
    // substitute the actual indexed field name for <indexfield>

    db.<collection>.find( { <indexfield>: Math.pow(2,63) } );
  • 如果一个collection中的索引字段是文档(或者数值),可以执行:

// substitute the actual collection name for <collection>
// substitute the actual indexed field name for <indexfield>

db.<collection>.find({
$where: function() {
function findVal(obj, val) {
if (obj === val)
return true;

for (const child in obj) {
if (findVal(obj[child], val)) {
return true;
}
}
return false;
}
return findVal(this.<indexfield>, Math.pow(2, 63));
}
})


以上是关于MongoDB 哈希索引的主要内容,如果未能解决你的问题,请参考以下文章

如何定义复合和哈希 mongodb 索引?

B+树索引和哈希索引的区别

mongodb06---索引

详解MongoDB索引优化

使用 MD5 哈希作为索引

如何将代码片段存储在 mongodb 中?