SELECT * FROM t1 CROSS JOIN t2; SELECT * FROM t1 JOIN t2; -- 同 CROSS JOIN SELECT * FROM t1, t2; -- 逗號語法等同
無條件時產生 M×N 行,極度危險,僅用於測試或極小集合。
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id; -- INNER 可省略 SELECT * FROM t1 JOIN t2 ON t1.id = t2.id;
僅返回雙方均滿足 ON 條件的行。
| 類型 | 語法 | 語義 |
|---|---|---|
| 左外連接 | LEFT [OUTER] JOIN | 保留左表所有行,右表無匹配則 NULL |
| 右外連接 | RIGHT [OUTER] JOIN | 保留右表所有行,左表無匹配則 NULL |
-- user 為左表,user_action 為右表 SELECT u.id, u.name, a.action FROM user u LEFT JOIN user_action a ON u.id = a.user_id WHERE a.user_id IS NULL; -- 僅保留左表獨有行
結果:daodao(id=3)無對應 action,action 顯示 NULL。
ON:通用條件,支援任意運算式USING(col):雙表連接欄位同名時的簡寫WHERE:內連接等同於 ON;外連接中 WHERE 會過濾掉 NULL 行,轉為內連接語義MySQL 採用 Nested Loop Join(嵌套循環連接):
join_buffer 做 Block Nested Loop,效能仍遠遜於索引查找NOT NULL 欄位 IS NULL 時,匹配到第一行即停止搜尋-- 原查詢:b 在前導致全掃描 SELECT * FROM a, b LEFT JOIN c ON c.key=a.key LEFT JOIN d ON d.key=a.key WHERE b.key=d.key; -- 優化:將 b 移至 FROM 首位 SELECT * FROM b, a LEFT JOIN c ON c.key=a.key LEFT JOIN d ON d.key=a.key WHERE b.key=d.key;
| 檢查項目 | 優化動作 | 驗證方式 |
|---|---|---|
| 被驅動表連接欄有索引? | 建立索引 / 調整 JOIN 順序 | EXPLAIN type=ref/eq_ref |
| 驅動表是否為小結果集? | 加 WHERE 過濾 / 子查詢先縮小 | EXPLAIN rows 最小 |
| SELECT 列是否過多? | 只取需要列,利用覆蓋索引 | Extra=Using index |
| 是否產生臨時表/filesort? | 調整 ORDER BY/GROUP BY 欄位順序 | Extra 無 Using temporary/filesort |
| 字符集/排序規則是否一致? | 統一 utf8mb4_general_ci | SHOW CREATE TABLE 對比 |
STRAIGHT_JOIN:強制按 FROM 順序連接,阻止優化器重排USE INDEX(idx) / IGNORE INDEX(idx):提示/禁止特定索引核心心法: JOIN 優化的本質是「讓優化器以最小代價找到匹配行」。永遠從
EXPLAIN看起,確認驅動表、被驅動表、索引使用、臨時表產生四大指標,再針對性調整 SQL 或結構。