建立索引不僅要考慮 WHERE 條件欄位,ORDER BY 排序欄位同樣重要。本文透過 PostgreSQL 執行計畫說明如何建立複合索引避免額外排序操作,提升查詢效能。
SELECT * FROM mytable
WHERE category_id = 1 AND user_id = 2
ORDER BY adddate DESC;
若只在 category_id、user_id、adddate 分別建立單欄索引,資料庫可能只使用 WHERE 條件索引,執行完仍需對結果集進行 Sort(排序) 操作,造成效能損耗。
CREATE INDEX mytable_categoryid_userid_adddate
ON mytable (category_id, user_id, adddate);
索引欄位順序:WHERE 條件的等值比較欄位在前,範圍/排序欄位在後。
EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
ORDER BY adddate DESC;
-- QUERY PLAN:
-- Sort (cost=2.03..2.03 rows=1 width=16)
-- -> Index Scan using mytable_categoryid_userid_addda
-- on mytable (cost=0.00..2.02 rows=1 width=16)
出現 Sort 節點表示資料庫需額外排序。
EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
ORDER BY category_id DESC, user_id DESC, adddate DESC;
-- QUERY PLAN:
-- Index Scan Backward using mytable_categoryid_userid_addda
-- on mytable (cost=0.00..2.02 rows=1 width=16)
關鍵技巧:在 ORDER BY 中加入 WHERE 條件欄位(category_id DESC, user_id DESC),雖然這兩欄位實際上不會改變排序結果,但能讓查詢規劃器確認索引順序完全符合,直接採用 Index Scan Backward 從索引尾端反向掃描,完全避免排序。
上述原理在 MySQL (InnoDB)、PostgreSQL、SQL Server 等主流關聯式資料庫皆適用。實務上請搭配 EXPLAIN (MySQL) 或 EXPLAIN ANALYZE (PostgreSQL) 驗證執行計畫。
當 WHERE 條件涉及多個表格欄位時,建議:
索引設計是資料庫效能調校的核心技能,建議開發者養成「寫查詢前先想索引、寫完後必看執行計畫」的習慣。