MySQL **僅支援 Nested Loop Join (NLJ)**,無 Hash Join、Sort Merge Join。
原理:以外層驅動表結果集為循環基礎,逐行以關聯條件查詢內層表,合併結果;多表遞迴同理。
MySQL 5.1.26
-- user_group:用戶-群組關係
CREATE TABLE user_group (
user_id INT NOT NULL, group_id INT NOT NULL, user_type INT NOT NULL,
gmt_create DATETIME, gmt_modified DATETIME, status VARCHAR(16),
KEY idx_user_group_uid (user_id)
) ENGINE=MyISAM;
-- group_message:群組訊息
CREATE TABLE group_message (
id INT PRIMARY KEY AUTO_INCREMENT,
gmt_create DATETIME, gmt_modified DATETIME,
group_id INT, user_id INT, author VARCHAR(32), subject VARCHAR(128),
KEY idx_group_message_author_subject (author, subject(16)),
KEY idx_group_message_author (author),
KEY idx_group_message_gid_uid (group_id, user_id)
) ENGINE=MyISAM;
-- group_message_content:訊息內容
CREATE TABLE group_message_content (
group_msg_id INT NOT NULL, content TEXT,
KEY group_message_content_msg_id (group_msg_id)
) ENGINE=MyISAM;
SELECT m.subject msg_subject, c.content msg_content
FROM user_group g, group_message m, group_message_content c
WHERE g.user_id = 1
AND m.group_id = g.group_id
AND c.group_msg_id = m.id;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | g | ref | idx_user_group_uid | idx_user_group_uid | 4 | const | 1 | |
| 1 | SIMPLE | m | ref | idx_group_message_gid_uid | idx_group_message_gid_uid | 4 | g.group_id | 10 | |
| 1 | SIMPLE | c | ref | group_message_content_msg_id | group_message_content_msg_id | 4 | m.id | 1 |
g:ref 走 idx_user_group_uid,user_id=1 過濾,預估 1 行m:對每行 g,用 g.group_id 走 idx_group_message_gid_uid 查詢,預估 10 行c:對每行 m,用 m.id 走 group_message_content_msg_id 查詢,預估 1 行STRAIGHT_JOIN 強制type=ALL 表示無索引可用,需優先優化MySQL 8.0.18+ 引入 **Hash Join**(關閉 NLJ 時使用),但預設仍以 NLJ 為主。理解 NLJ 原理仍是調優基礎。