Index Cond 是在索引上定位,Filter 是撈出來再逐筆比
這兩個關鍵字並排在同一個節點裡時,它們講的是完全不同的成本——而它們的分界就是「索引夠不夠」的判準。
| 關鍵字 | 發生什麼事 | 成本 |
|---|---|---|
Index Cond | 直接在 B-Tree 索引樹上定位 | 快 |
Filter | 索引條件不夠,把資料載進記憶體後一筆一筆用 CPU 比對 | 每一筆都要付 |
Rows Removed by Filter | 比對完被丟棄的列數 | 這個數字就是無用功的量 |
一個真實的例子
-> Bitmap Heap Scan on pg060 s (actual time=496.333..496.333 rows=0 loops=15)
Recheck Cond: (a.vrfy_wkym = vrfy_wkym)
Filter: ((a.div_no = (div_no)::bpchar) AND (a.emp_org_id = (emp_org_id)::bpchar))
Rows Removed by Filter: 38118
-> Bitmap Index Scan on pg060_idx1 (actual ... rows=38118 loops=15)
Index Cond: (vrfy_wkym = a.vrfy_wkym)攤開來看發生了什麼:
索引只幫上 vrfy_wkym 這一個條件
→ 撈出該年月整整 38,118 筆
→ div_no 和 emp_org_id 只能在記憶體裡逐筆比
→ 38,118 筆【全部】不符合,被丟棄
→ 真正要的是 0 筆
→ 而且這整個過程重複了 15 次 → 38,118 × 15 ≈ 57 萬次比對
單次 496 ms,這一個節點就吃掉 7.4 秒。
判準
Rows Removed by Filter很大(數千到數十萬),就代表資料庫做了大量無用功。
而且它指出了處方:被 Filter 丟掉的那些欄位,就是該補進索引的欄位——見 複合索引的欄位 = Index Cond 的欄位 + Filter 裡的等值欄位。
Rows Removed by Filter 和「回傳幾列 vs 看過幾列」的對應關係見 WHERE 決定回傳幾列,索引才決定要看過幾列。