定位低效SQL与不同的Extra类型(转载)
這個博客是轉載自[1]
臨時關閉ONLY_FULL_GROUP_BY
雖然下面的SQL全部照搬自[1],但是會發現部分SQL的執行結果還是和預期的Extra取值不太一樣。
應該是Mysql8.x相對于mysql5.7之前的版本做了更多的底層的優化。
| Extra | ? 數據準備 | 數據說明 | SQL | 結果說明 |
| Using where | create table user (id int primary key,name varchar(20),sex varchar(5), index(name))engine=innodb; ? insert into user values(1, 'shenjian','no'); insert into user values(2, 'zhangsan','no'); insert into user values(3, 'lisi', 'yes'); insert into user values(4, 'lisi', 'no'); | 用戶表:id主鍵索引,name普通索引(非唯一),sex無索引; 四行記錄:其中name普通索引存在重復記錄lisi; | explain select * from user where sex="no"; | 本例雖然Extra字段說明使用了where條件過濾,但type屬性是ALL,表示需要掃描全部數據,仍有優化空間。 ? 常見的優化方法為,在where過濾屬性上添加索引。 |
| Using index | 同上 | 同上 | explain select id,name from user where name='shenjian';(Using index) | Extra為Using index說明,SQL所需要返回的所有列數據均在一棵索引樹上,而無需訪問實際的行記錄。 |
| Using index condition | 同上 | 同上 | explain select id,name,sex from user where name='shenjian';(NULL) | sex不在索引樹上 |
| Using filesort | 同上 | 同上 | explain select * from user order by sex;(Using filesort) | Extra為Using filesort說明,得到所需結果集,需要對所有記錄進行文件排序。 ? 這類SQL語句性能極差,需要進行優化。 |
| Using temporary | 同上 | 同上 | explain select * from user group by name order by sex;(Using temporary; Using filesort?) | Extra為Using temporary說明,需要建立臨時表(temporary table)來暫存中間結果。 ? 這類SQL語句性能較低,往往也需要進行優化。 |
| Using join buffer | 同上 | 同上 | explain select * from user where id in(select id from user where sex='no');(Using where NULL) | ? |
?
上面的建表語句中使用了索引覆蓋index(name),那么在下面的SQL語句中就能實現提速。
?
來比較3個很有意思的東西:
mysql> explain select sex from user where name='shenjian'; +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ | 1 | SIMPLE | user | NULL | ref | name | name | 83 | const | 1 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)mysql> explain select id from user where name='shenjian'; +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | user | NULL | ref | name | name | 83 | const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)mysql> explain select id from user where sex='female'; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | user | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 25.00 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+上述三個十分接近的SQL,但是explain的的Extra都各不相同。
Extra=Null,表示不用回表,想要查詢的數據剛好與普通索引在同一個節點中
Extra=Index,表示不用回表,想要查詢的column(primary key)與普通索引在同一個節點中
Extra=Using where,表示需要回表,想要查詢的column(primary key)與普通索引不在同一個節點,需要先獲取普通索引,再回表通過普通索引來獲取id數據
?
?
速度排序(從左往右越來越慢):
Using Index>Using Where>Using filesort>Using temporary
由于mysql8相對于mysql5的改動,上述不少Extra的取值目前暫時沒有實現。
結尾:
explain是SQL優化中最常用的工具,搞定type和Extra,explain也就基本搞定了。
?
Reference:
[1]如何利用工具,迅猛定位低效SQL? | 1分鐘系列
?
總結
以上是生活随笔為你收集整理的定位低效SQL与不同的Extra类型(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 诡异的select *语句报错事件
- 下一篇: 涨知识!了解现今的深圳seo公司如何运作