Postgresql索引結構-Hash


前言

  本篇介紹Postgresql中Hash索引的結構以及應用場景。

什么是Hash?

  Hash的思想是將一個小數字(從0到N−1,總共N個值)與任何數據類型的值關聯起來。這樣的關聯稱為Hash函數。所獲得的數字可以用作一個常規數組的索引,其中存儲對表行(tid)的引用。這個數組的元素被稱為Hash buckets(hash桶)——一個桶可以存儲多個tid。

  Hash函數越一致地按桶分配源值,就越好。但即使是一個好的hash函數有時也會對不同的源值產生相同的結果——這稱為沖突。因此,一個桶可以存儲不同鍵對應的tid,所以,從索引中獲取的tid需要重新檢查。

哈希索引結構與訪問

  哈希索引與Btree索引一樣。對於某個數據類型的值(索引鍵),我們的任務是快速查找匹配的TID。

  當插入到索引中時,PostgreSQL中的哈希函數總是返回“integer”類型,取值范圍是2^32≈40億。桶的數量最初等於兩個,然后根據數據大小動態增加。桶號可以使用位運算從哈希碼計算出來。這個桶就是我們放置TID的桶。但是光存儲TID是不夠的,因為匹配不同鍵的tid可以放在同一個存儲桶中。為了解決這個問題,除了TID之外,還可以將索引鍵存儲在一個桶中,但這將大大增加索引大小。為了節省空間,桶中存儲的不是索引鍵,而是索引鍵的哈希碼。

  當對索引進行檢索時,我們首先用哈希函數計算輸入鍵得到桶號,剩下的工作就是遍歷桶的內容,並只返回帶有適當哈希碼的匹配tid。然而,兩個不同的鍵不僅可能進入同一個桶中,而且可能具有相同的四字節哈希碼——這種沖突無法避免。因此,access method要求通用索引引擎通過重新檢查表行中的條件來驗證每個TID(索引引擎可以通過可見性檢查來完成此操作)。

Fig 1 哈希索引頁結構示意圖

 

 如上圖所示,哈希索引使用了四種頁面(灰色矩形):

  • Meta page:頁碼0,其中包含關於索引內部內容的信息。
  • Bucket pages:索引的主頁,以“哈希碼 - TID”對存儲數據。
  • Overflow pages:與bucket page結構相同,當一個頁面不足以容納一個bucket時使用。
  • Bitmap pages:跟蹤當前已清除並且可以在其他存儲桶中重用的Overflow page。

從索引頁元素開始的向下箭頭表示tid,即對表行的引用。

 注意哈希索引不能減小大小。如果我們刪除一些索引行,那么一旦分配了頁面,就不會返回給操作系統,這些頁面只會在清理后為新數據重用。減少索引大小的唯一選項是使用REINDEX重建索引或VACUUM FULL命令。

使用限制:

1、PG10版本之前,WAL日志不記錄create hash index操作,在數據恢復和流復制時會出現問題。

2、有序的索引鍵在hash桶中不一定有序,因此只能用於等值查詢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM