全表掃描和索引掃描的適用場景是相反的
Full Table Scan(全表掃描):從第一列開始依序逐列讀取,逐筆判斷條件,直到找完。通常發生在這張表沒有可用索引的時候。
SELECT * FROM member WHERE name = 'emily' 在沒有索引時,會從第一筆開始讀、檢查 name 是否等於 'emily',不符就往下一列。表裡有 1,000,000 筆資料時,最糟情況要讀完並比對 100 萬筆——條件寫得再精準也一樣,見 WHERE 決定回傳幾列,索引才決定要看過幾列。
兩條存取路徑的步驟
| 全表掃描 | 索引掃描 | |
|---|---|---|
| 1 | 讀取表中的每一行 | 利用索引查找符合條件的索引項 |
| 2 | 檢查每一行是否符合查詢條件 | 根據索引項定位到表中的資料行 |
| 3 | 返回符合條件的行 | 返回符合條件的行 |
差別在第一步:索引掃描先定位再讀資料,全表掃描沒有定位這一步,只能全部讀過再比。索引掃描多出來的代價是第二步那次回表。
適用場景
| 全表掃描 | 索引掃描 |
|---|---|
| 小表、資料量較小的表 | 大表、資料量較大的表 |
| 查詢需要訪問表中大部分資料 | 查詢條件選擇性高(結果只占一小部分) |
| 表上沒有適合的索引 | 表上有適合的索引 |
所以「全表掃描」不等於「做錯了」:要撈的本來就是大半張表時,逐列讀一遍比走索引一筆筆回表更便宜——這也是低選擇性欄位即使建了索引,資料庫仍然會選全表掃描的原因,見 索引是拿寫入換查詢,寫多讀少的表加索引是純虧。
在執行計畫裡這兩條路徑長什麼樣,見 Index Cond 是在索引上定位,Filter 是撈出來再逐筆比。