# MySQL EXPLAIN
EXPLAIN å
³é®åå¯ä»¥ç¨äºè·å SQL è¯å¥æ§è¡è®¡åçç¸å
³ä¿¡æ¯ï¼å¨ MySQL 8.0 ä¸ï¼EXPLAIN æ¯æå¤§å¤æ° SQL è¯å¥ï¼å¦ SELECT ãDELETE ãINSERT ãREPLACEãå UPDATE ã示ä¾å¦ä¸ï¼
```shell
mysql> EXPLAIN SELECT * FROM employees;
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 299379 | NULL |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
```
æ³¨ï¼æ¬ç¯æç« çæµè¯æ°æ®æ¥æºäº MySQL 宿¹æä¾ç [Employees Sample Database](https://dev.mysql.com/doc/employee/en/)ï¼å
¶æ°æ®åºç»æå¦ä¸ï¼
以ä¸åå«ä»ç» EXPLAIN è¾åºç»æä¸åä¸ªåæ®µçå«ä¹ï¼
## 1. id
id ä¸ºè¡æ è¯ç¬¦ï¼åæ¶ä¹è¡¨ç¤ºè¯å¥æ§è¡çä¼å
级ï¼å¼è¶å¤§åä¼å
级è¶é«ãç¹æ®æ
åµä¸ï¼å¦ææè¡è¯å¥å¼ç¨äºå
¶ä»å¤è¡ç»æéçå¹¶éï¼å该å¼å¯ä»¥ä¸º NULLã示ä¾å¦ä¸ï¼
```shell
# 该FROMåå¥åªæ¯ç¨äºæ¼ç¤ºï¼å¹¶æ²¡æä»»ä½å®é
æä¹
mysql> EXPLAIN SELECT COUNT(1) FROM (SELECT emp_no FROM salaries) AS t;
+----+-------------+------------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+------+---------+-------------+
| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 2757635 | NULL |
| 2 | DERIVED | salaries | index | NULL | PRIMARY | 7 | NULL | 2757635 | Using index |
+----+-------------+------------+-------+---------------+---------+---------+------+---------+-------------+
```
```shell
# æ¥è¯¢å·¥èµå¤§äº500000æé¨é¨ç¼å·çäºd007çææéåçç¼å·
mysql> EXPLAIN SELECT emp_no FROM salaries WHERE salary>500000 UNION ALL SELECT emp_no FROM dept_emp WHERE dept_no = "d007";
+----+--------------+------------+------+---------------+---------+---------+-------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+------+---------------+---------+---------+-------+---------+--------------------------+
| 1 | PRIMARY | salaries | ALL | NULL | NULL | NULL | NULL | 2837161 | Using where |
| 2 | UNION | dept_emp | ref | dept_no | dept_no | 4 | const | 91566 | Using where; Using index |
| NULL | UNION RESULT | | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+------+---------------+---------+---------+-------+---------+--------------------------+
```
## 2. select_type
select_type ç¨äºè¡¨ç¤ºæ¥è¯¢çç±»åï¼å¸¸è§ç±»ååå
¶å«ä¹å¦ä¸ï¼
+ **SIMPLE**ï¼ä¸å
å«åæ¥è¯¢æè
UNION æä½çæ¥è¯¢ï¼
+ **PRIMARY**ï¼æ¥è¯¢ä¸å¦æå
å«ä»»ä½åæ¥è¯¢ï¼é£ä¹æå¤å±çæ¥è¯¢å被æ 记为 PRIMARY ï¼
+ **SUBQUERY**ï¼åæ¥è¯¢ä¸ç¬¬ä¸ä¸ª SELECT ï¼
+ **DEPENDENT SUBQUERY**ï¼åæ¥è¯¢ä¸ç第ä¸ä¸ª SELECTï¼åå³äºå¤é¨æ¥è¯¢ï¼
+ **UNION**ï¼UNION æä½ç第äºä¸ªæè
ä¹åçæ¥è¯¢ï¼
+ **DEPENDENT UNION**ï¼UNION æä½ç第äºä¸ªæè
ä¹åçæ¥è¯¢,åå³äºå¤é¨æ¥è¯¢ï¼
+ **UNION RESULT**ï¼UNION 产ççç»æéï¼
+ **DERIVED**ï¼åºç°å¨ FROM åå¥ä¸çåæ¥è¯¢ã
è¿é以æ¥è¯¢ç±»å为 SUBQUERY çæ
åµè¿è¡æ¼ç¤ºï¼ç¤ºä¾å¦ä¸ï¼
```shell
# æ ¹æ®åå·¥ç¼å·æ¥è¯¢åå·¥å§ååå
¶å·¥èµæ»å
mysql> EXPLAIN SELECT first_name,(SELECT sum(salary) FROM salaries WHERE emp_no = 10001) FROM employees WHERE emp_no = 10001;
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | employees | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
| 2 | SUBQUERY | salaries | ref | PRIMARY | PRIMARY | 4 | const | 17 | NULL |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
```
## 3. table
表示è¯å¥æ§è¡çç®æ 表ï¼é¤äºæ£å¸¸ç表åæè¡¨å«åå¤ï¼è¿ä¼åºç°ä»¥ä¸åå¼ï¼
- ****ï¼è¾åºç»æä¸ç¼å·ä¸º M çè¡ä¸ç¼å·ä¸º N çè¡çç»æéçå¹¶éã
- ****ï¼è¾åºç»æä¸ç¼å·ä¸º N çè¡çç»æéï¼derived è¡¨ç¤ºè¿æ¯ä¸ä¸ªæ´¾çç»æéï¼å¦ FROM åå¥ä¸çæ¥è¯¢ã
- ****ï¼è¾åºç»æä¸ç¼å·ä¸º N çè¡çç»æéï¼subquery è¡¨ç¤ºè¿æ¯ä¸ä¸ªç©ååæ¥è¯¢ã
## 4. type
type åæ®µæ¯è¿è¡æ§è½å¤æçéè¦ä¾æ®ï¼å®è¡¨ç¤º MySQL 使ç¨ä½ç§æ¹å¼æ¥æ¥æ¾ç®æ æ°æ®éï¼ä¸åæ¥æ¾æ¹å¼ä¼å¯¼è´ä¸åçæ§è½å¼éï¼å¸¸è§æ¥æ¾æ¹å¼åå
¶æ§è½è¡¨ç°æç
§ç±é«å°ä½çé¡ºåºæåºå¦ä¸ï¼
**1. system**ï¼è¿æ¯ const ç±»åçä¸ä¸ªç¹ä¾ï¼åªä¼åºç°å¨å¾
æ¥è¯¢çè¡¨åªæä¸è¡æ°æ®çæ
åµä¸ã
**2. const**ï¼å¸¸åºç°å¨ä¸»é®æå¯ä¸ç´¢å¼ä¸å¸¸éå¼è¿è¡æ¯è¾çåºæ¯ä¸ï¼æ¤æ¶æ¥è¯¢æ§è½æ¯æä¼çã
```shell
mysql> EXPLAIN SELECT * FROM employees WHERE emp_no = 10008;
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | employees | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
```
**3. eq_ref**ï¼å½è¿æ¥ä½¿ç¨çæ¯å®æ´çç´¢å¼å¹¶ä¸æ¯ PRIMARY KEY æ UNIQUE NOT NULL INDEX æ¶ä½¿ç¨å®ã
```shell
# è¿éåå·¥é¨é¨å
³ç³»è¡¨ dept_no çèå主é®ä¸º emp_no + dept_no ï¼å³åå·¥ç¼å·+é¨é¨æ å·
mysql> EXPLAIN SELECT * FROM employees e,dept_emp d WHERE e.emp_no = d.emp_no AND dept_no = "d005";
+----+-------------+-------+--------+-----------------+---------+---------+--------------------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------+---------+---------+--------------------+------+-----------------------+
| 1 | SIMPLE | d | ref | PRIMARY,dept_no | dept_no | 4 | const | 1 | Using index condition |
| 1 | SIMPLE | e | eq_ref | PRIMARY | PRIMARY | 4 | employees.d.emp_no | 1 | NULL |
+----+-------------+-------+--------+-----------------+---------+---------+--------------------+------+-----------------------+
```
**4. ref**ï¼å½è¿æ¥ä½¿ç¨çæ¯åç¼ç´¢å¼æè¿æ¥æ¡ä»¶ä¸æ¯ PRIMARY KEY æ UNIQUE INDEX æ¶å使ç¨å®ã
```shell
# è¿éä»
使ç¨äºåç¼ç´¢å¼emp_noï¼æä»¥å
¶ç±»å为 ref , è䏿¯ eq_ref
mysql> EXPLAIN SELECT * FROM employees e,dept_emp d WHERE e.emp_no = d.emp_no;
+----+-------------+-------+------+---------------+---------+---------+--------------------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+--------------------+--------+-------+
| 1 | SIMPLE | e | ALL | PRIMARY | NULL | NULL | NULL | 299379 | NULL |
| 1 | SIMPLE | d | ref | PRIMARY | PRIMARY | 4 | employees.e.emp_no | 1 | NULL |
+----+-------------+-------+------+---------------+---------+---------+--------------------+--------+-------+
```
**5. ref_or_null**ï¼ç±»ä¼¼äº ref ç±»åçæ¥è¯¢ï¼ä½æ¯éå äºå¯¹ NULL å¼åçæ¥è¯¢ã示ä¾è¯å¥å¦ä¸ï¼
```sql
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
```
**6. index_merge**ï¼è¯¥èæ¥ç±»å表示使ç¨äºç´¢å¼è¿è¡åå¹¶ä¼åï¼ç¤ºä¾å¦ä¸ï¼
```shell
mysql> EXPLAIN SELECT * FROM dept_emp WHERE dept_no = "d004" AND emp_no < 10020;
+----+-------------+----------+-------------+-----------------+-----------------+---------+------+------+-----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------------+-----------------+-----------------+---------+------+------+-----------------------------------------------+
| 1 | SIMPLE | dept_emp | index_merge | PRIMARY,dept_no | dept_no,PRIMARY | 8,4 | NULL | 1 | Using intersect(dept_no,PRIMARY); Using where |
+----+-------------+----------+-------------+-----------------+-----------------+---------+------+------+-----------------------------------------------+
```
**7. range**ï¼ä½¿ç¨ç´¢å¼è¿è¡èå´æ«æï¼å¸¸è§äº betweenã> ã< è¿æ ·çæ¥è¯¢æ¡ä»¶ã
```shell
mysql> EXPLAIN SELECT * FROM employees WHERE emp_no > 10000;
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | range | PRIMARY | PRIMARY | 4 | NULL | 149689 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
```
**8. index**ï¼ç´¢å¼è¿æ¥ç±»åä¸ ALL ç¸åï¼åªæ¯æ«æçæ¯ç´¢å¼æ ï¼é常åºç°å¨ç´¢å¼æ¯è¯¥æ¥è¯¢çè¦çç´¢å¼çæ
åµï¼
```shell
mysql> EXPLAIN SELECT emp_no FROM employees;
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | index | NULL | PRIMARY | 4 | NULL | 299379 | Using index |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
```
**9. ALL**ï¼å
¨è¡¨æ«æï¼æçæå·®çæ¥æ¾æ¹å¼ã
```shell
mysql> EXPLAIN SELECT * FROM employees WHERE first_name ="Bezalel";
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 299379 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
```
## 5. possible_keys
è¡¨ç¤ºå¨æ§è¡è¿ç¨ä¸å¯è½ä¼ç¨å°åªäºç´¢å¼æ¥è¿è¡ä¼åã
## 6. key
è¡¨ç¤ºå¨æ§è¡è¿ç¨ä¸å®é
ç¨å°çç¨äºä¼åçç´¢å¼ã
## 7. key_len
表示使ç¨å°çç´¢å¼çåèæ°ã
## 8. ref
æ¾ç¤ºåªäºåæå¸¸éä¸ key å䏿å®çç´¢å¼è¿è¡æ¯è¾ã
## 9. rows
MySQL ä¸ºäºæ¾å°ç®æ è¡è读åçææè¡çæ°éï¼è¿æ¯ä¸ä¸ªä¼°ç®çå¼ã
## 10. Extra
Extra å主è¦ç¨äºæ¾ç¤ºé¢å¤çä¿¡æ¯ï¼å¸¸è§ä¿¡æ¯åå
¶å«ä¹å¦ä¸ï¼
**1. Using where** ï¼MySQL æå¡å¨ä¼å¨åå¨å¼ææ£ç´¢è¡ååè¿è¡è¿æ»¤ã示ä¾å¦ä¸ï¼
```shell
# first_name åæ®µæ¯ä¸ä¸ªæ®éçåï¼éç´¢å¼å
mysql> EXPLAIN SELECT * FROM employees WHERE first_name = "Sumant";
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 299379 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
```
**2. Using filesort**ï¼é常åºç°å¨ GROUP BY æ ORDER BY è¯å¥ä¸ï¼ä¸æåºæåç»æ²¡æåºäºç´¢å¼ï¼æ¤æ¶éè¦ä½¿ç¨æä»¶å¨å
åä¸è¿è¡æåºãå 为使ç¨ç´¢å¼æåºçæ§è½å¥½äºä½¿ç¨æä»¶æåºï¼æä»¥åºç°è¿ç§æ
åµå¯ä»¥èèéè¿æ·»å ç´¢å¼è¿è¡ä¼åã示ä¾å¦ä¸ï¼
```shell
mysql> EXPLAIN SELECT * FROM employees ORDER BY first_name ;
+----+-------------+-----------+------+---------------+------+---------+------+--------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+----------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 299379 | Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+--------+----------------+
```
**3. Using index**ï¼ä½¿ç¨äºè¦çç´¢å¼è¿è¡æ¥è¯¢ï¼æ¤æ¶ä¸éè¦è®¿é®è¡¨ï¼ä»ç´¢å¼ä¸å°±å¯ä»¥è·åå°æéçå
¨é¨æ°æ®ã示ä¾å¦ä¸ï¼
```shell
mysql> EXPLAIN SELECT emp_no FROM employees;
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | index | NULL | PRIMARY | 4 | NULL | 299379 | Using index |
+----+-------------+-----------+-------+---------------+---------+---------+------+--------+-------------+
```
**4. Using temporary**ï¼è¡¨ç¤ºéè¦ä½¿ç¨ä¸´æ¶è¡¨æ¥å¤çæ¥è¯¢ï¼å¸¸åºç°å¨ GROUP BY æ ORDER BY è¯å¥ä¸ï¼ç¤ºä¾å¦ä¸ï¼
```shell
mysql> EXPLAIN SELECT first_name,count(first_name) FROM employees GROUP BY first_name ;
+----+-------------+-----------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+---------------------------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 299379 | Using temporary; Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+--------+---------------------------------+
```
## åèèµæ
æ´å¤åæ°ç说æå¯ä»¥åè MySQL 宿¹ææ¡£ï¼https://dev.mysql.com/doc/refman/8.0/en/explain-output.html