explain(解釋),在 Mysql 中 做爲一個關鍵詞,用來解釋 Mysql 是如何執行語句,能夠鏈接 select 、delete、insert、update 語句。sql
一般咱們使用 explain 鏈接 一條 select 語句,查看運行狀態,判斷是否須要優化。編程
栗子:bash
explain select s.name,s.id,s.age,s.create_time from student s;
函數
輸出:性能
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | s | NULL | ALL | NULL | NULL | NULL | NULL | 7 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
複製代碼
官方:優化
EXPLAIN [explain_type] explainable_stmt
explain_type: {
EXTENDED
| PARTITIONS
| FORMAT = format_name
}
explainable_stmt: {
SELECT statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement
}
複製代碼
輸出的列名:ui
type 列描述了表的 join 類型,如下以 查詢的最優到最差的排序列出了可能值:spa
SELECT * FROM tbl_name WHERE primary_key=1;
SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2;
複製代碼
栗子:code
explain select s.* from student s where s.id = 1
複製代碼
輸出:orm
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | s | NULL | const | PRIMARY | PRIMARY | 8 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
複製代碼
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
複製代碼
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
複製代碼
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
複製代碼
value IN (SELECT primary_key FROM single_table WHERE some_expr)
複製代碼
value IN (SELECT key_column FROM single_table WHERE some_expr)
複製代碼
SELECT * FROM tbl_name
WHERE key_column = 10;
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name
WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
複製代碼
假設有以下的 sql:根據訂單日期 和 店員id 查詢 訂單信息(已建立了訂單日期的索引),查詢結果返回 18條記錄。
SELECT * FROM orders
WHERE YEAR(o_orderdate) = 1992 AND MONTH(o_orderdate) = 4
AND o_clerk LIKE '%0223';
複製代碼
Explain 輸出執行計劃:
問題所在:
SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE '%0223';
複製代碼
從新使用 Explain 查看 執行計劃:
發現:type 由 ALL 變爲 range ,訂單日期索引得以利用,被掃描的記錄由 15萬 降爲 3.3萬左右。
爲 店員字段建立索引:
CREATE INDEX i_o_clerk ON orders(o_clerk);
複製代碼
再次輸出執行計劃:
發現:基本上並無什麼變化,新建的索引沒有被利用,緣由在於 該字段是 模糊查詢,過濾指定後綴的 店員信息。可是索引對於後綴過濾會失效(儘管索引對於前綴有效果)。
修改sql,全量過濾店員字段:
SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE 'Clerk#000000223';
複製代碼
再次輸出執行計劃:
發現:可用索引增長,真正使用的索引變爲 店員字段上的索引,被掃描的行由 3.3萬降爲 1546。
建立以下索引:
CREATE INDEX io_clerk_date ON orders(o_clerk, o_orderdate)
複製代碼
** :這裏將 o_clerk 放在 o_orderdate 以前,由於 o_orderdate 使用了 範圍,最左前綴索引原則。
再次輸出執行計劃:
發現:使用了組合索引,被掃描記錄即爲輸出的18條記錄。效率已最優化。
屢次優化的總結:
Type | Possible keys | Key | Rows Scanned | Duration (seconds) | Extra info | Rows returned |
---|---|---|---|---|---|---|
all | NULL | NULL | 1.50M | 1.201 | Using where | 18 |
range | i_o_orderdate | i_o_orderdate | 32642 | 0.281 | Using index condition; Using where | 18 |
range | i_o_orderdate, i_o_clerk | i_o_clerk | 1546 | 0.234 | Using index condition; Using where | 18 |
range | i_o_orderdate, i_o_clerk, i_o_clerk_date | i_o_clerk_date | 18 | 0.234 | Using index condition | 18 |
歡迎關注 編程那點事兒,隨時隨地,想學就學~