2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不再支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

11.3. 多列索引 #

可以在表的多個列上定義索引。例如,如果您有一個具有以下形式的表

CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);

(假設您將您的 /dev 目錄儲存在資料庫中…),並且您經常執行如下查詢

SELECT name FROM test2 WHERE major = constant AND minor = constant;

那麼,對 majorminor 列一起定義一個索引可能是合適的,例如:

CREATE INDEX test2_mm_idx ON test2 (major, minor);

目前,只有 B-tree、GiST、GIN 和 BRIN 索引型別支援多鍵列索引。是否存在多個鍵列與是否可以向索引新增 INCLUDE 列是獨立的。索引最多可以有 32 列,包括 INCLUDE 列。(構建 PostgreSQL 時可以更改此限制;請參閱檔案 pg_config_manual.h。)

多列 B-tree 索引可以用於涉及索引列的任何子集的查詢條件,但當對最左邊的列存在等值約束時,該索引效率最高。確切的規則是,最左邊列上的等值約束,加上第一個沒有等值約束的列上的任何不等值約束,都將始終用於限制需要掃描的索引部分。右側列上的約束將在索引中進行檢查,因此它們總是可以節省對實際表的訪問,但它們不一定能減少需要掃描的索引部分。如果 B-tree 索引掃描可以有效應用跳躍掃描最佳化,那麼它將在遍歷索引時透過重複的索引搜尋來應用每個列約束。這可以減少需要讀取的索引部分,即使一個或多個列(在查詢謂詞中最不顯著的索引列之前)缺乏常規的等值約束。跳躍掃描的工作原理是透過內部生成一個動態等值約束,該約束匹配索引列中的每個可能值(但僅在給定一個缺少查詢謂詞的等值約束的列,並且僅當生成的約束可以與查詢謂詞中的後續列約束一起使用時)。

例如,給定一個在 (x, y) 上的索引,以及查詢條件 WHERE y = 7700,B-tree 索引掃描可能會應用跳躍掃描最佳化。這通常發生在查詢規劃器預期對於每個可能的 N 值(或對於表中實際儲存的每個 x 值)重複執行 WHERE x = N AND y = 7700 搜尋是給定表中可用索引的最快方法時。這種方法通常僅在 x 的不同值非常少的情況下才會被採用,以至於規劃器預期掃描將跳過大部分索引(因為其大部分葉子頁面可能不包含相關的元組)。如果 x 的不同值很多,那麼將需要掃描整個索引,因此在大多數情況下,規劃器將優先選擇順序表掃描而不是使用索引。

跳躍掃描最佳化也可以選擇性地應用,在至少包含一些有用查詢謂詞約束的 B-tree 掃描期間。例如,給定一個在 (a, b, c) 上的索引和查詢條件 WHERE a = 5 AND b >= 42 AND c < 77,索引可能需要從 a = 5 和 b = 42 的第一個條目掃描到 a = 5 的最後一個條目。具有 c >= 77 的索引條目永遠不需要在表級別進行過濾,但跳過它們在索引內部是否有益可能有所不同。當發生跳躍時,掃描會啟動一個新的索引搜尋,從當前 a = 5 和 b = N 組的末尾(即,在索引中第一個元組 a = 5 AND b = N AND c >= 77 出現的位置)重新定位到下一組的開頭(即,在索引中第一個元組 a = 5 AND b = N + 1 出現的位置)。

多列 GiST 索引可以用於涉及索引列的任何子集的查詢條件。其他列上的條件會限制索引返回的條目,但第一列上的條件對於確定需要掃描多少索引非常重要。如果 GiST 索引的第一列只有少量不同的值,即使其他列有許多不同的值,該索引的有效性也會相對較低。

多列 GIN 索引可以用於涉及索引列的任何子集的查詢條件。與 B-tree 或 GiST 不同,無論查詢條件使用哪個(些)索引列,索引搜尋的有效性都是相同的。

多列 BRIN 索引可以用於涉及索引列的任何子集的查詢條件。與 GIN 類似,但與 B-tree 或 GiST 不同,無論查詢條件使用哪個(些)索引列,索引搜尋的有效性都是相同的。在單個表上擁有多個 BRIN 索引而不是一個多列 BRIN 索引的唯一原因是擁有不同的 pages_per_range 儲存引數。

當然,每個列都必須使用適合索引型別的運算子;涉及其他運算子的子句將不被考慮。

應謹慎使用多列索引。在大多數情況下,單列索引就足夠了,並且可以節省空間和時間。超過三個列的索引除非表的用法非常特殊,否則不太可能有幫助。有關不同索引配置的優缺點的討論,請參閱 Section 11.5Section 11.9

提交更正

如果您在文件中看到任何不正確、與您對特定功能的經驗不符或需要進一步闡明的內容,請使用 此表單 來報告文件問題。