11.5. 善用多個索引

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

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

為了組合多個索引,系統掃描每個所需的索引會在記憶體中準備一個 bitmap,給予回報與索引條件符合的資料表中資料列的位置。然後根據查詢的需要對 bitmap 進行 AND 運算和 OR 運算。最後,存取並回傳實際資料表中的資料列。資料列按磁碟循序存取,因為這是 bitmap 的檔案結構;這意味著原始索引的任何排序都會遺失,因此如果查詢具有 ORDER BY 子句,則需要單獨的排序步驟。由於這個原因,並且因為每次額外的索引掃描都會增加額外的時間,所以計劃程序有時會選擇使用簡單的索引掃描,即使可以使用其他索引也是如此。

除了最簡單的應用程序之外,還有各種可能有用的索引組合,資料庫開發人員必須進行權衡以決定提供哪些索引。有時多欄位索引是最好的,但有時最好建立單獨的索引並依賴索引組合功能。例如,如果您的工作負載包含有時只涉及欄位 x 的查詢混合,有時只涉及欄位 y,有時只有兩個欄位,您可以選擇在 x 和 y 上建立兩個單獨的索引,依靠索引組合來處理查詢使用兩個欄位。您還可以在 (x, y) 上建立多個欄位索引。對於涉及兩個欄位的查詢,此索引通常比索引組合更有效,但如第 11.3 節所述,對於僅涉及 y 的查詢,它幾乎無用,因此它不應該是唯一的索引。多欄位索引和 y 上單獨索引的組合可以很好地發揮作用。對於僅涉及 x 的查詢,可以使用多列索引,儘管它會更大,因此比單獨 x 上的索引慢。最後一種方法是建立所有三個索引,但如果資料的搜尋頻率比更新頻率更高,並且所有三種類型的查詢都很常見,則這可能是合理的。如果其中一種類型的查詢比其他類型的查詢少得多,那麼您可能只想建立最符合常見類型的兩個索引。