系統梳理 SELECT 核心用法,補充 LIMIT 大偏移量效能陷阱與優化方案、UNION 去重行為、EXPLAIN 執行計劃關鍵欄位解讀,幫助開發者寫出高效查詢。
SELECT [DISTINCT] select_list
FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position} [ASC|DESC], ...]
[HAVING where_condition]
[ORDER BY {col_name | expr | position} [ASC|DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
SELECT * FROM huge_table LIMIT 1000000, 10 需掃描並丟棄前 100 萬行,IOPS 與 CPU 暴增,延遲隨偏移線性增長。
SELECT t.* FROM huge_table t INNER JOIN (SELECT id FROM huge_table ORDER BY id LIMIT 1000000, 10) tmp USING (id);
WHERE id > last_id ORDER BY id LIMIT 10(需 ID 遞增無間隙)。Using index 可避免回表。UNION:合併結果並去重(排序/哈希去重,額外開銷)。UNION ALL:直接合併,**不去重**,效能顯著更高。| 欄位 | 關注重點 |
|---|---|
| type | system > const > eq_ref > ref > range > index > ALL(越左越好) |
| possible_keys / key | 可用索引 vs 實際用索引(NULL 表全掃) |
| key_len | 索引長度,判斷聯合索引用了幾列 |
| rows | 預估掃描行數(越小越好) |
| Extra | Using index(覆蓋索引)、Using where、Using temporary、Using filesort(需優化) |
| 反模式 | 修正 |
|---|---|
| SELECT * | 顯式列出所需欄位,減少網路/IO/記憶體 |
| WHERE 對欄位用函數 | 改寫為範圍查詢(如 date_col >= '2024-01-01') |
| 隱式類型轉換 | 字串比較加引號,數字不加 |
| OR 連接不同索引欄位 | 改用 UNION ALL 分開查詢 |
| ORDER BY 非索引欄位 | 建立對應索引或接受 filesort |
-- 方案 A:延遲關聯(通用) SELECT t.col1, t.col2 FROM large_table t JOIN (SELECT id FROM large_table WHERE status=1 ORDER BY id LIMIT 10000, 20) tmp USING (id); -- 方案 B:書籤分頁(高併發、ID 遞增) SELECT col1, col2 FROM large_table WHERE status = 1 AND id > 123456 ORDER BY id LIMIT 20;