支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10

64.6. 雜湊索引 #

64.6.1. 概述 #

PostgreSQL 包含持久性磁碟雜湊索引的實作,這些索引完全可從崩潰中恢復。 任何資料類型都可以由雜湊索引來建立索引,包括沒有明確線性排序的資料類型。 雜湊索引僅儲存被索引資料的雜湊值,因此對被索引的資料欄位大小沒有限制。

雜湊索引僅支援單欄索引,且不允許唯一性檢查。

雜湊索引僅支援 = 運算子,因此指定範圍運算的 WHERE 子句將無法利用雜湊索引。

每個雜湊索引元組僅儲存 4 位元組的雜湊值,而不是實際的欄位值。 因此,在為較長的資料項目(例如 UUID、URL 等)建立索引時,雜湊索引可能比 B 樹小得多。 缺少欄位值也使得所有雜湊索引掃描都是有損的。 雜湊索引可以參與點陣圖索引掃描和向後掃描。

雜湊索引最適合在較大表格上使用相等掃描的 SELECT 和 UPDATE 繁重工作負載。 在 B 樹索引中,搜尋必須下降到樹直到找到葉頁。 在具有數百萬列的表格中,這種下降可能會增加資料的存取時間。 雜湊索引中相當於葉頁的部分稱為儲存桶頁。 相比之下,雜湊索引允許直接存取儲存桶頁,從而可能減少較大表格中的索引存取時間。 這種“邏輯 I/O”的減少在比 shared_buffers/RAM 大的索引/資料上變得更加明顯。

雜湊索引旨在應對雜湊值的不均勻分佈。 如果雜湊值分佈均勻,則直接存取儲存桶頁效果很好。 當插入意味著儲存桶頁已滿時,額外的溢位頁會鏈接到該特定儲存桶頁,從而在本機擴展與該雜湊值匹配的索引元組的儲存空間。 在查詢期間掃描雜湊儲存桶時,我們需要掃描所有溢位頁。 因此,對於某些資料,在所需的區塊存取次數方面,不平衡的雜湊索引實際上可能比 B 樹更糟糕。

由於溢位的情況,我們可以說雜湊索引最適合唯一、幾乎唯一的資料或每個雜湊儲存桶的列數較少的資料。 避免問題的一種可能方法是使用部分索引條件從索引中排除高度非唯一的值,但在許多情況下這可能並不適合。

與 B 樹一樣,雜湊索引執行簡單的索引元組刪除。 這是一種延遲維護作業,用於刪除已知可以安全刪除的索引元組(那些項目識別碼的 LP_DEAD 位已設定的元組)。 如果插入發現頁面上沒有可用空間,我們會嘗試透過移除已死索引元組來避免建立新的溢位頁。 如果頁面當時已釘選,則無法進行移除。 已死索引指標的刪除也會在 VACUUM 期間發生。

如果可以,VACUUM 也會嘗試將索引元組壓縮到盡可能少的溢位頁上,從而最大程度地減少溢位鏈。 如果溢位頁變成空的,則溢位頁可以回收以供其他儲存桶重複使用,但我們永遠不會將它們返回給作業系統。 目前沒有縮小雜湊索引的規定,除了使用 REINDEX 重建它之外。 也沒有減少儲存桶數量的規定。

雜湊索引可能會隨著索引列數的增加而擴充儲存桶頁的數量。 選擇雜湊金鑰到儲存桶編號的對應,以便可以逐步擴充索引。 當要將新儲存桶新增到索引時,只需要「分割」一個現有的儲存桶,並根據更新的金鑰到儲存桶編號的對應將其某些元組傳輸到新的儲存桶。

擴充在前景中發生,這可能會增加使用者插入的執行時間。 因此,雜湊索引可能不適合列數快速增加的表格。

64.6.2. 實作 #

雜湊索引中有四種頁面:元頁面(零頁),其中包含靜態分配的控制資訊; 主要儲存桶頁面; 溢位頁面; 以及點陣圖頁面,用於追蹤已釋放且可用於重新使用的溢位頁面。 出於定址目的,點陣圖頁面被視為溢位頁面的子集。

掃描索引和插入元組都需要找到給定元組應該位於的儲存桶。 為此,我們需要來自元頁面的儲存桶計數、highmask 和 lowmask; 但是,出於效能原因,不希望為每個此類操作鎖定和釘選元頁面。 相反,我們在每個後端的 relcache 項目中保留元頁面的快取副本。 只要自上次快取重新整理以來,目標儲存桶沒有被分割,這將產生正確的儲存桶對應。

主要儲存桶頁面和溢位頁面是獨立分配的,因為相對於其儲存桶數量,任何給定的索引可能需要更多或更少的溢位頁面。 雜湊碼使用一組有趣的定址規則來支援可變數量的溢位頁面,同時不必在建立主要儲存桶頁面後四處移動它們。

表格中被索引的每一列都由雜湊索引中的單一索引元組表示。雜湊索引元組儲存在 bucket 頁面中,如果空間不足,則儲存在溢出頁面中。我們透過將任何一個索引頁面中的索引條目按雜湊碼排序來加速搜尋,從而允許在索引頁面內使用二元搜尋。但是請注意,對於 bucket 的不同索引頁面之間的雜湊碼的相對順序,*沒有*任何假設。

用於擴展雜湊索引的 bucket 分裂演算法太複雜,不值得在此提及,但更詳細的描述可以在 src/backend/access/hash/README 中找到。分裂演算法是防崩潰安全的,如果沒有成功完成,可以重新啟動。

提交更正

如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。