處理複雜關聯 SQL 優化,核心考量四點:
EXPLAIN 觀察 rows 判斷瓶頸STRAIGHT_JOIN 強制連接順序驗證假設SELECT c.yh_id, c.yh_dm, c.yh_mc, c.mm, c.yh_lx,
a.jg_id, a.jg_dm, a.jg_mc, a.jgxz_dm, d.js_dm yh_js
FROM a, b, c
LEFT JOIN d ON d.yh_id = c.yh_id
WHERE a.jg_id = b.jg_id
AND b.yh_id = c.yh_id
AND a.yx_bj = 'Y'
AND c.sc_bj = 'N'
AND c.yx_bj = 'Y'
AND c.yh_dm = '006939748XX';
執行時間:**750 ms**,僅回傳 1 筆資料。
+----+-------+------+------+----------------+------+--------+------+-------+-------------+
| id | table | type | key | key_len | ref | rows | Extra |
+----+-------+------+------+----------------+------+--------+------+-------+-------------+
| 1 | a | ALL | NULL | NULL | NULL | 52,616 | Using where | ← 全表掃描
| 1 | d | index| PRIMARY| 196 | NULL | 54,584 | Using index | ← 索引全掃描
+----+-------+------+------+----------------+------+--------+------+-------+-------------+
d 表無 yh_id 索引,導致 54,584 行掃描。新增索引:
ALTER TABLE d ADD INDEX ind_yh_id(yh_id);
結果:d 表掃描行數降至 **272 行**,但總時間 **0.77 秒** 未改善(a 表仍全掃)。
c 表有高選擇性條件 yh_dm = '006939748XX'(僅 2 筆),新增索引:
ALTER TABLE c ADD INDEX ind_yh_dm(yh_dm);
但優化器仍選 a 表為驅動表。分析原因:
b.yh_id 索引,但 b 表無此索引,b 表大(105,809 行)b.jg_id 索引(主鍵包含),優化器判斷成本較低ALTER TABLE b ADD INDEX ind_yh_id(yh_id);
再次執行,執行計劃變為:
c (ref, rows=2) → d (ref, rows=272) → b (ref, rows=531) → a (eq_ref, rows=1)
**執行時間:0.00 秒(< 1ms)**,較原始 **提升 750 倍**。
| 步驟 | 動作 | 效果 |
|---|---|---|
| 1 | 分析 EXPLAIN 找出大 rows 的表 |
定位瓶頸 |
| 2 | 為高選擇性條件欄位建索引 | 降低驅動表掃描量 |
| 3 | 補齊關聯欄位索引(特別是被驅動表) | 讓優化器選擇最佳連接順序 |
| 4 | 必要時用 STRAIGHT_JOIN/FORCE INDEX 驗證 |
確認最優路徑 |