【MongoDB】哈希索引(Hashed Indexes)

本章內容:

  • 哈希函數
  • 創建哈希索引
  • 注意事項

哈希索引使用索引字段值的哈希來維護索引條目。

哈希索引可以用作哈希分片鍵來對數據進行分片基於哈希的分片將字段的哈希索引用作分片鍵,以跨分片羣集對數據進行分區。

使用哈希分片鍵對集合進行分片使數據分佈更隨機。有關更多詳細信息,請參見哈希分片

 

一、哈希函數

哈希索引使用哈希函數來計算索引字段值的哈希。 [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));

    }

})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章