【MongoDB】哈希索引(Hashed Indexes)

本文探讨了哈希索引在MongoDB中的应用,包括如何创建哈希索引、哈希函数的工作原理以及使用哈希分片键进行数据分片的方法。文中还提到了哈希索引的限制,如不支持多键索引和复合索引,以及对浮点数的处理限制。
摘要由CSDN通过智能技术生成

本章内容:

  • 哈希函数
  • 创建哈希索引
  • 注意事项

哈希索引使用索引字段值的哈希来维护索引条目。

哈希索引可以用作哈希分片键来对数据进行分片基于哈希的分片将字段的哈希索引用作分片键,以跨分片群集对数据进行分区。

使用哈希分片键对集合进行分片使数据分布更随机。有关更多详细信息,请参见哈希分片

 

一、哈希函数

哈希索引使用哈希函数来计算索引字段值的哈希。 [1]哈希函数折叠嵌入的文档并计算整个值的哈希,但不支持多键(即数组)索引。

提示

使用哈希索引解析查询时,MongoDB自动计算哈希值。应用程序不需要计算哈希。

[1]从版本4.0开始,mongo shell提供了convertShardKeyToHashed()方法。此方法使用与哈希索引相同的哈希函数,可用于查看一个键的哈希值。

 

二、创建哈希索引

要创建哈希索引,请指定hash作为索引键的值,如以下示例所示:

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

三、注意事项

MongoDB支持任何单个字段的哈希索引。哈希函数折叠嵌入的文档并为整个值计算哈希,但不支持多键(即数组)索引。

不能创建具有哈希索引字段的复合索引,也不能在哈希索引上指定唯一约束;但是,可以在同一字段上创建哈希索引和升序/降序(即非哈希)索引:MongoDB将标量索引用于范围查询。

 

1.上限2^53

警告

MongoDB哈希索引在哈希之前将浮点数截断为64位整数。例如,哈希索引将为具有2.3、2.2和2.9的值的字段存储相同的值。为防止冲突,请勿对不能准确地转换为64位整数的浮点数使用哈希索引。

MongoDB哈希索引不支持大于2^53的浮点值

若要查看一个键的哈希值是多少,请参见convertShardKeyToHashed()

 

2.PowerPC和2^63

PowerPC(英语:Performance Optimization With Enhanced RISC – Performance Computing,有时简称PPC)是一种精简指令集(RISC)架构的中央处理器(CPU),其基本的设计源自IBM的POWER(Performance Optimized With Enhanced RISC;《IBM Connect电子报》2007年8月号译为“增强RISC性能优化”)架构。POWER是1991年,Apple、IBM、Motorola组成的AIM联盟所发展出的微处理器架构。PowerPC是整个AIM联盟平台的一部分,并且是到目前为止唯一的一部分。但苹果电脑自2005年起,将旗下电脑产品转用Intel CPU。

对于哈希索引,MongoDB 4.2确保PowerPC上浮点值2^63的哈希值与其他平台一致。

尽管可能包含大于2^53的浮点值的字段上的哈希索引是不受支持的配置,但是客户端仍可以在索引字段具有值2^63的位置插入文档。

要列出部署中所有集合的所有哈希索引,可以在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);

        };

      });

   });

});

要检查索引字段是否包含值2^63,请对集合和索引字段运行以下操作:

  • 如果索引字段类型是标量而不是文档:
//将<collection>替换为实际的集合名称
 
//将<indexfield>替换为实际的索引字段名称

db.<collection>.find( { <indexfield>: Math.pow(2,63) } );
  • 如果索引字段类型是文档(或标量),则可以运行:
//将<collection>替换为实际的集合名称

//将<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));

    }

})

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值