在實務上搜尋資料的時候,可能不會像前面的舉例那麼簡單,單純用一個欄位 id
去尋找資料,而是藉由多個欄位的條件去篩選出多筆資料。
像這樣的情況,可能就需要將多個欄位都設成 Index,稱為 Multi-Column Index。在 PostgreSQL 中,最多可以將 32 個欄位 設定成同一個 Index。
官方文件提到,如果 Index 設為 (A, B, C)
,當查詢條件為 A, B, C
的子集合時,也可以使用 Index,但這是從最左邊開始檢查是否為 Index 組合的子集合。
A multicolumn B-tree index can be used with query conditions that involve any subset of the index's columns, but the index is most efficient when there are constraints on the leading (leftmost) columns.
因此,如果查詢條件常見的是 (A, B, C)
以及 (A, B)
,代表欄位 C 為 optional,那麼應該將 Index 的順序設為 (A, B, C)
,將 C 放在最右邊,這樣才能確保 Index 能被有效使用。
假設我們有一張 quizzes
表,搜尋的欄位為 school_type
、subject
、chapter_code
,並且設定 Index 如下:
CREATE TABLE quizzes (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
school_type TEXT NOT NULL,
subject TEXT NOT NULL,
chapter_code TEXT NOT NULL
);
CREATE INDEX idx_quizzes_school_subject_chapter
ON quizzes (school_type, subject, chapter_code);
school_type + subject + chapter_code
:由於完全符合 Index 定義的順序,因此會使用 Index。Index order | school_type | subject | chapter_code | Query 是否使用 Index |
---|---|---|---|---|
Query 使用欄位 | O | O | O | O |
school_type + subject
:仍然符合 Index 順序的左側部分,因此會使用 Index。Index order | school_type | subject | chapter_code | Query 是否使用 Index |
---|---|---|---|---|
Query 使用欄位 | O | O | X | O |
subject + chapter_code
:這組條件沒有包含 Index 的第一個欄位 (school_type
),因此不會使用 Index。Index order | school_type | subject | chapter_code | 是否使用 Index |
---|---|---|---|---|
Query 使用欄位 | X | O | O | X |
Index order | school_type | subject | chapter_code | 是否使用 Index |
---|---|---|---|---|
測試 1 | O | O | O | O |
測試 2 | O | O | X | O |
測試 3 | X | O | O | X |
不過從 Query Plan 上看到的 Index 搜尋方式,似乎跟之前看到的 Index Scan 不一樣?下一篇我們就來看這個第一次看到的 Bitmap Scan 是什麼東西吧~
https://www.postgresql.org/docs/current/indexes-multicolumn.html