資料庫索引解析:給網頁開發者的指南

Backend2026-09-13TryQuickToolBox

你的網頁應用程式在開發階段感覺很順暢,但隨著資料成長,原本毫秒內回傳的查詢現在卻要花上好幾秒。使用者開始抱怨,資料庫 CPU 也飆高。罪魁禍首通常是缺少或誤用索引。索引是後端開發者最具槓桿效應的技能之一,卻經常被誤解。本指南將說明資料庫索引的運作原理、何時使用,以及如何避免常見陷阱。

什麼是資料庫索引?

把索引想像成教科書後面的索引。你不用翻遍每一頁來找某個主題,而是查閱索引,它會指引你到正確的頁面。資料庫索引的運作方式類似:它是一種資料結構,讓資料庫引擎能快速找到資料列,而不必掃描整張表。

如果沒有索引,像 SELECT * FROM users WHERE email = 'alice@example.com' 這樣的查詢會強制進行全表掃描——資料庫會讀取每一列,直到找到符合的資料。若在 email 上建立索引,資料庫就能直接跳到符合的資料列。

索引的底層運作原理

大多數關聯式資料庫預設使用 B-tree(平衡樹)索引。B-tree 會保持資料排序,並以對數時間支援搜尋、循序存取、插入和刪除。這就是為什麼即使有數百萬列,索引查找依然快速。

其他索引類型包括:

對大多數網頁應用程式來說,B-tree 索引是主力。

何時建立索引

索引並非免費——它們會佔用儲存空間並拖慢寫入。請策略性地建立索引:

然而,請避免為很少查詢或基數極低的資料行(例如布林旗標)建立索引,除非它們與其他資料行搭配使用。

索引類型及其使用案例

索引類型 最適合 範例
單一資料行 簡單篩選 CREATE INDEX idx_email ON users(email);
複合 依多個資料行篩選的查詢 CREATE INDEX idx_name_age ON users(last_name, first_name);
唯一 強制唯一性 CREATE UNIQUE INDEX idx_username ON users(username);
部分 為資料列子集建立索引 CREATE INDEX idx_active ON users(email) WHERE active = true;
覆蓋 只需索引資料行的查詢 CREATE INDEX idx_covering ON users(email, name);

如何建立與驗證索引

建立索引很簡單。例如,在 PostgreSQL 中:

CREATE INDEX idx_users_email ON users(email);

建立索引後,請驗證它是否被使用。使用 EXPLAIN(或 EXPLAIN ANALYZE)來查看查詢計畫:

EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'alice@example.com';

尋找「Index Scan」或「Index Only Scan」,而不是「Seq Scan」。如果你看到循序掃描,可能是因為型別不符、對資料行使用函式,或統計資訊過舊,導致索引未被使用。

常見的索引錯誤

  1. 為所有東西建立索引:太多索引會拖慢寫入並浪費空間。
  2. 忽略複合索引的順序:對於 (a, b) 上的複合索引,只依 b 篩選的查詢無法有效使用該索引。
  3. 對已建立索引的資料行使用函式:WHERE YEAR(created_at) = 2025 會阻止索引使用。請改用範圍條件:WHERE created_at >= '2025-01-01' AND created_at < '2026-01-01'。
  4. 未更新統計資訊:資料庫依賴統計資訊來選擇索引。請定期執行 ANALYZE。
  5. 忽略寫入開銷:每個 INSERT、UPDATE 和 DELETE 都必須更新索引。對於寫入密集的表,請謹慎選擇。

進階技巧

覆蓋索引

覆蓋索引包含查詢所需的所有資料行,因此資料庫可以直接從索引擷取資料,而不必存取資料表。這可以大幅加速讀取密集的查詢。

部分索引

如果你經常查詢某個資料列子集(例如活躍使用者),部分索引會比完整索引更小、更快。

僅索引掃描

有些資料庫支援僅索引掃描,所有需要的資料都在索引中。這是最快的索引存取類型。

監控與維護索引

索引可能因更新和刪除而隨時間膨脹。在 PostgreSQL 中,VACUUM 和 REINDEX 有助於維持效能。在 MySQL 中,OPTIMIZE TABLE 可以重建索引。請定期檢閱慢查詢日誌,以找出缺少的索引。

常見問題

如何知道我的查詢是否使用索引?

在查詢前使用 EXPLAIN 指令(或 EXPLAIN ANALYZE)。輸出會顯示資料庫使用索引掃描還是循序掃描。

索引會太多嗎?

會。每個索引都會增加寫入操作的開銷並佔用儲存空間。請根據讀寫比例取得平衡。

叢集索引與非叢集索引有何不同?

叢集索引決定資料表中資料列的實際順序(例如 InnoDB 的主鍵)。非叢集索引是另一個指向資料列的結構。一張表只能有一個叢集索引,但可以有多個非叢集索引。

準備好最佳化你的資料庫了嗎?從分析慢查詢並在需要的地方加入索引開始。若需快速格式化與驗證 JSON,試試我們的 JSON Formatter——免費且完全在瀏覽器中執行。