2025年9月25日: PostgreSQL 18 釋出!
支援的版本:當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10

65.6. 雜湊索引 #

65.6.1. 概述 #

PostgreSQL 包含一種持久化磁碟雜湊索引的實現,該實現完全可崩潰恢復。任何資料型別都可以透過雜湊索引進行索引,包括沒有明確線性排序的資料型別。雜湊索引僅儲存被索引資料的雜湊值,因此對被索引的資料列的大小沒有限制。

雜湊索引僅支援單列索引,並且不允許進行唯一性檢查。

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

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

雜湊索引最適合用於對大型表進行等值掃描的 SELECT 和 UPDATE 密集型工作負載。在 B-tree 索引中,搜尋必須透過樹的層級一直下降到找到葉子節點。在擁有數百萬行的表中,這種下降會增加資料訪問時間。在雜湊索引中,相當於葉子節點的部分被稱為桶頁(bucket page)。相比之下,雜湊索引允許直接訪問桶頁,從而可能減少大型表的索引訪問時間。這種“邏輯 I/O”的減少在索引/資料大於 shared_buffers/RAM 時會更加明顯。

雜湊索引的設計旨在應對雜湊值分佈不均的情況。如果雜湊值分佈均勻,則直接訪問桶頁效果很好。當插入導致桶頁滿時,額外的溢位頁會被連結到該特定桶頁,區域性擴充套件儲存匹配該雜湊值的索引元組。在查詢期間掃描雜湊桶時,我們需要掃描所有的溢位頁。因此,對於某些資料,不平衡的雜湊索引在所需塊訪問次數方面可能比 B-tree 更差。

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

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

如果可能,VACUUM 還會嘗試將索引元組壓縮到儘可能少的溢位頁上,從而最小化溢位鏈。如果一個溢位頁變空,溢位頁就可以被回收以供其他桶重複使用,但我們永遠不會將其返回給作業系統。目前除了使用 REINDEX 重建索引外,沒有其他方法可以縮小雜湊索引。同樣也沒有減少桶數量的方法。

隨著被索引行數的增加,雜湊索引可能會增加桶頁的數量。雜湊鍵到桶號的對映選擇方式使得索引可以逐步擴充套件。當需要向索引新增一個新桶時,必須“分裂”一個現有的桶,並將該桶的一部分元組根據更新後的鍵到桶號的對映轉移到新桶中。

擴充套件操作在前端執行,這可能會增加使用者插入操作的執行時間。因此,對於行數快速增長的表,雜湊索引可能不適用。

65.6.2. 實現 #

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

掃描索引和插入元組都需要定位給定元組應該在哪一個桶中。為此,我們需要元資料頁中的桶數、highmask 和 lowmask;然而,出於效能考慮,不希望每次此類操作都鎖定和固定元資料頁。相反,我們在每個後端(backend)的 relcache 條目中保留元資料頁的快取副本。只要目標桶自上次快取重新整理以來未被分裂,這將產生正確的桶對映。

主桶頁和溢位頁是獨立分配的,因為任何給定的索引相對於其桶的數量可能需要更多的或更少的溢位頁。雜湊碼使用一套特殊的定址規則來支援可變數量的溢位頁,而無需在建立主桶頁後移動它們。

表中被索引的每一行在雜湊索引中都由一個單獨的索引元組表示。雜湊索引元組儲存在桶頁中,如果存在的話,也在溢位頁中。我們透過將任何一個索引頁中的索引項按雜湊碼排序來加快搜索速度,從而允許在索引頁內使用二分搜尋。但請注意,對於一個桶中不同索引頁之間的雜湊碼相對順序,*沒有任何*假設。

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

提交更正

如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。