支援的版本:目前 (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

11.5. 合併多個索引 #

單一索引掃描只能使用查詢子句,該子句使用索引的欄位及其運算符類的運算符,並與 AND 連接。例如,如果給定一個 (a, b) 上的索引,則像 WHERE a = 5 AND b = 6 這樣的查詢條件可以使用該索引,但像 WHERE a = 5 OR b = 6 這樣的查詢則無法直接使用該索引。

幸運的是,PostgreSQL 能夠合併多個索引(包括多次使用同一個索引),以處理單一索引掃描無法實現的情況。系統可以在多個索引掃描中形成 ANDOR 條件。例如,像 WHERE x = 42 OR x = 47 OR x = 53 OR x = 99 這樣的查詢可以分解為對 x 上的索引的四個獨立掃描,每個掃描使用一個查詢子句。然後將這些掃描的結果進行 OR 運算以產生結果。另一個例子是,如果我們在 xy 上有單獨的索引,則像 WHERE x = 5 AND y = 6 這樣的查詢的一種可能實現是將每個索引與適當的查詢子句一起使用,然後將索引結果進行 AND 運算,以識別結果列。

為了合併多個索引,系統掃描每個需要的索引,並在記憶體中準備一個位圖,給出報告為符合該索引條件的資料表列的位置。然後根據查詢的需要,將位圖進行 AND 運算和 OR 運算。最後,存取並返回實際的資料表列。資料表列以物理順序存取,因為這就是位圖的佈局方式;這意味著原始索引的任何排序都會遺失,因此如果查詢具有 ORDER BY 子句,則需要單獨的排序步驟。由於這個原因,以及因為每個額外的索引掃描都會增加額外的時間,因此即使有其他可用於使用的索引,規劃器有時也會選擇使用簡單的索引掃描。

在除了最簡單的應用程式之外的所有應用程式中,可能有各種有用的索引組合,資料庫開發人員必須權衡利弊,以決定要提供哪些索引。有時多欄索引是最好的,但有時最好建立單獨的索引,並依賴索引組合功能。例如,如果您的工作負載包含的查詢組合有時只涉及欄位 x,有時只涉及欄位 y,有時同時涉及這兩個欄位,則您可以選擇在 xy 上建立兩個單獨的索引,並依賴索引組合來處理使用這兩個欄位的查詢。您也可以在 (x, y) 上建立一個多欄索引。對於涉及這兩個欄位的查詢,此索引通常比索引組合更有效,但如第 11.3 節中所討論的,它對於僅涉及 y 的查詢幾乎沒有用,因此它不應該是唯一的索引。多欄索引和 y 上的單獨索引的組合可以很好地服務。對於僅涉及 x 的查詢,可以使用多欄索引,儘管它會比單獨在 x 上的索引更大,因此速度更慢。最後一個替代方案是建立所有三個索引,但只有在資料表搜尋的頻率遠高於更新的頻率,並且所有三種類型的查詢都很常見時,這才可能是合理的。如果其中一種查詢的類型遠不如其他類型常見,您可能會滿足於僅建立最符合常見類型的兩個索引。

提交更正

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