iT邦幫忙

2025 iThome 鐵人賽

DAY 5
4

https://ithelp.ithome.com.tw/upload/images/20250901/20177885KAlbYvK7ul.png

在 PostgreSQL 中當查詢使用 Index,我們目前看到了兩種方式:Index ScanBitmap Scan。 接下來就分別來看看他們各自的特性,以及適用的情境。

Index Scan

Index Scan 搜尋時,主要會有兩個步驟:

  1. Index Lookup:先從 B-Tree 找到符合條件的 row 的位置(tuple)。
  2. Heap Fetch:根據找到的位置,回到 table 讀取實際的資料。

https://ithelp.ithome.com.tw/upload/images/20250807/20177885i3cXwT5IcV.png

什麼時候會用到?

  1. 查詢條件篩選後回傳的資料筆數少(例如 WHERE id = 123
  2. Index 欄位具有高度選擇性(High Selectivity),查詢的結果佔整個表的一小部分。

比如先前我們從 users table 內只用 id 查詢一筆特定的資料,使用的就是 Index Scan。

https://ithelp.ithome.com.tw/upload/images/20250807/20177885tB4ISXdmUt.png

Bitmap Scan

而 Bitmap scan 的運作方式為:

  1. Bitmap Index Scan:先透過 Index 找到多個符合條件的 row,並將它們標記在 Bitmap 結構內。
  2. Bitmap Heap Scan:一次性批量存取這些 row,減少 Heap Fetch 的次數,提高效能。

https://ithelp.ithome.com.tw/upload/images/20250807/20177885XEQv5iaOHx.png

有看到差異了嗎?相較於 Index Scan 每次找到 row 的位置就會回到 Heap 找實際的資料,Bitamp 是找到多筆 row 的位置後,一次性的回去找實際的資料。這樣的方式可以比 Index Scan 減少來回在 Heap 找資料的次數。

什麼時候會用到?

  1. 查詢條件篩選後,符合條件的 row 數量較多,但還不到需要全表掃描(Sequential Scan)。
  2. 當 Index 欄位的選擇性較低(例如 WHERE status = 'active',但 active 佔了一半的資料)。
  3. 多個 Index 需要合併查詢,例如 WHERE email LIKE '%example.com' AND created_at > '2024-01-01'

比如上一篇我們從 quizzes 中搜尋的條件分別落在不同的欄位,PostgreSQL 的 Planner 就認為 Bitmap Scan 比 Index scan 還要適合。

https://ithelp.ithome.com.tw/upload/images/20250807/20177885sQ0VdqgKrO.png

仔細看這張圖,也可以看到這兩個步驟:

  1. (第 4 行)Bitmap Index Scan 先找到所有符合條件的 row(9 rows)。
  2. (第 1 行)Bitmap Heap Scan 批量存取這些 row,減少來回的開銷。

Index Scan vs. Bitmap Scan 差異比較

特性 Index Scan Bitmap Scan
適用情境 查詢範圍較小 查詢範圍較大
存取方式 逐筆讀取 Index 和 Table 先從 Index 批次找到資料,然後批次讀取 Table
效率 適合小範圍查詢 適合大範圍篩選
回表(Heap Fetch) 每筆都回表一次 批量回表,降低 I/O

重點回顧

  1. 如果查詢結果筆數較少,PostgreSQL 會選擇 Index Scan,因為 Heap Fetch 的開銷較小。
  2. 如果查詢結果筆數較多,PostgreSQL 會選擇 Bitmap Scan,因為它能批量 Heap Fetch,提高效率。

參考資料

https://www.postgresql.org/docs/current/indexes-bitmap-scans.html


上一篇
Day 4 - Multi-Column Index:順序對效能的影響
系列文
PostgreSQL 效能優化 30 天挑戰:從 Index 到 Transaction 的深入探索5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言