可以在表的多個列上定義索引。例如,如果您有一個具有以下形式的表
CREATE TABLE test2 ( major int, minor int, name varchar );
(假設您將您的 /dev
目錄儲存在資料庫中…),並且您經常執行如下查詢
SELECT name FROM test2 WHERE major =constant
AND minor =constant
;
那麼,對 major
和 minor
列一起定義一個索引可能是合適的,例如:
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.5 和 Section 11.9。
如果您在文件中看到任何不正確、與您對特定功能的經驗不符或需要進一步闡明的內容,請使用 此表單 來報告文件問題。