低價服裝網(wǎng)站建設百度認證官網(wǎng)申請
1、前言
提到sql性能分析,可能都會想到explain,它在mysql里被稱為執(zhí)行計劃,也就是說可以通過該命令看出mysql在通過優(yōu)化器分析之后如何執(zhí)行sql。mysql的內(nèi)置優(yōu)化器十分強大,它能幫我們把sql再次優(yōu)化,以最低的成本去執(zhí)行。我們的項目中通常會添加慢sql打印的功能,這些慢sql就是需要我們?nèi)シ治龊蛢?yōu)化的目標。
2、explain的使用
explain關鍵字使用很簡單,只需要在目標sql前面加上該關鍵字然后執(zhí)行即可,如下所示EXPLAIN SELECT * FROM user;
可以看到,返回了十幾個字段,這里主要介紹幾個重要字段type、key、rows、Extra。
type 表示 mysql 訪問數(shù)據(jù)的方式,常見的有全表掃描(all)、遍歷索引(index)、區(qū)間查詢(range)、常量或等值查詢(ref、eq_ref)、主鍵等值查詢(const)、當表中只有一條記錄時(system)。其效率由好到壞依次為
system > const > eq_ref > ref > range > index > all
key 表示查詢過程實際會用到的索引名稱
rows 表示查詢過程中可能需要掃描的行數(shù),這個數(shù)據(jù)不一定準確,是mysql 抽樣統(tǒng)計的一個數(shù)據(jù)
Extra 表示一些額外的信息,通常會顯示是否使用了索引,是否需要排序,是否會用到臨時表等
對于上面那條sql,我并沒有創(chuàng)建額外的索引,其type為all,說明走了全表掃描,這種全表掃描效率是很低的,是優(yōu)化的重點。
現(xiàn)在分別給字段添加普通索引
alter table `user` add index name_index(name);
alter table `user` add index address_index(address);
alter table `user` add index age_index(age);
然后我們創(chuàng)建測試數(shù)據(jù),這里用一個存儲過程實現(xiàn),以注釋分割,依次執(zhí)行
-- 修改mysql分隔符為雙分號
delimiter ;;
-- 刪除存儲過程
drop procedure if exists makedata;;
-- 創(chuàng)建存儲過程
create procedure makedata()
begindeclare i int;set i=1;while i<=100000 doinsert into user(`name`,`address`,`sex`,`age`) values(concat('小明',i),concat('北京',i),'男','25');set i=i+1;end while;
end;;
-- 修改分隔符為單分號
delimiter ;
-- 執(zhí)行該存儲過程
call makedata();
然后分析一條sqlEXPLAIN SELECT * FROM user where age>24;
可以看到,雖然key里面給出了索引名稱,但是type類型依然是all,也就是說實際上我們的索引并未生效,這里就涉及一個回表查詢
了,所謂回表查詢,就是我們根據(jù)普通索引查詢到了索引字段和唯一主鍵索引字段,但是我們查詢的字段超出了這兩個,因此,還要去根據(jù)唯一主鍵索引去查詢其他字段的數(shù)據(jù)。從這里也可以看出,mysql優(yōu)化器在分析后認為還不如一開始就用全表查詢(至少只查一次)。那么回表查詢?nèi)绾谓鉀Q呢?最直接的方式就是只查詢索引字段和唯一主鍵字段,如下
但是這樣的話,有可能不滿足我們的需求,所以最直接的方式就是實現(xiàn)索引覆蓋
。所謂的索引覆蓋就是要查詢的字段建立一個聯(lián)合索引。
我們創(chuàng)建一個名字和年齡的索引字段alter table user add index name_age_index(name,age);
然后再去查詢
3、總結
這篇文章主要記錄了如何去分析一條sql的性能,然后引出了回表查詢、索引、創(chuàng)建存儲過程的相關知識,通過這些例子我們可以知道為什么不要去寫select * 查詢,當然,這里的內(nèi)容還是遠遠不夠的,需要我們多學習,多分析。