開發同學或多或少會遇到系統響應慢的問題,除了業務系統本身的問題外,常常會遇到sql查詢慢
的問題,這篇文章結合實際案例分析mysql innodb儲存引擎的索引優化,這篇文章不會介紹b+
樹的知識點,如果需要了解聚集索引和輔助索引特點的同學可以參考這篇文章,這篇文章主要會介紹三星索引
和icp優化
.
首先是檢視mysql的狀態,系統是否正常,常用的幾個命令如下:
#顯示狀態資訊(擴充套件show status like 『***』)
mysql> show status;
#顯示系統變數(擴充套件show variables like 『***』)
mysql> show variables\g;
#顯示innodb儲存引擎的狀態
mysql> show engine innodb status\g;
#檢視當前sql執行,包括執行狀態、是否鎖表等
mysql> show processlist ;
第二步是找出系統有哪些慢查詢sql,這個要通過slowlog來查詢,首先開啟慢查詢日誌,然後在對應日誌路徑找到mysql-slow.log,相關命令如下所示:
# 檢查是否開啟慢查詢日誌
show variables like '%slow%'
;# 如果沒有開啟,也可以在執行時動態開啟這個引數
set global slow_query_log=on;
# 設定慢查詢記錄查詢耗時多長的sql,這裡設定成100毫秒
set long_query_time = 0.1;
# 這裡休眠500毫秒試一下慢查詢日誌是否會記錄
select sleep(0.5)
找到了慢sql後比較常見的做法就是用explain命令分析sql執行計畫,檢視sql語句是否命中了索引,explain的用法可以參考mysql 效能優化神器 explain 使用分析,在優化過程中我們可能需要看到優化前後的查詢時間對比,這時候可以開啟profiling開關,檢視某條sql語句的執行耗時情況,分析是哪個步驟耗時較長,相關設定如下:
# 檢視是否開啟profiling
select @@profiling;
# 開profiling,注意測試完關閉該特性,否則耗費資源
set profiling=1;
# 檢視所有記錄profile的sql
show profiles;
# 檢視指定id的sql的詳情
show profile for query 1;
# 測試完,關閉該特性
set profiling=0;
乙個profiling例子:
三星索引的策略是根據查詢語句來建立聯合索引,比如有這樣一條sql,select groupid,addtime,status from order where groupid = 10010 order by addtime
,如何用三星索引來優化這條查詢呢?
前面的章節多次提到了icp技術
,那到底什麼是icp
呢,在介紹icp
之前我們先來看一下sql
語句的where條件提取規則:所有sql的where條件,都可以歸納為3大類:index key
,index filte
r和table filter
,下面的介紹以create table order (groupid int(11) default null, addtime datetime default null, status int(11) default null,key ix_groupid (groupid), key ix_addtime (addtime)) engine=innodb
這個表結構為例,假設我們分別單獨建立了groupid
和addtime
的索引,假設我們要執行這樣一條sqlselect groupid,addtime,status from order where groupid < 10010 and addtime > '1970' and status = 0
;,那sql執行計畫會是怎樣呢?
index key
index key
只是用來定位索引的起止範圍,因此只在索引第一次搜尋時使用,一次判斷即可;
從起始範圍之後讀到的每一條索引記錄,均需要判斷是否在index key的範圍內,以上面的sql為例,index key就是groupid,它的範圍是groupid < 10010.
index filter
用於過濾索引查詢範圍中不滿足查詢條件的記錄,因此對於索引範圍中的每一條記錄,均需要與index filter
進行對比,若不滿足index filter
則直接丟棄,繼續讀取索引下一條記錄,在前面的sql中,index filter
就是addtime > '1970'
,mysql會把這個過濾條件下推到儲存引擎層,icp就是index condition push down,不管是index key
還是index filter
對應的列必須新增了索引.
table filter
table filter
是where
條件最後一道防線,用於過濾通過前面索引的層層考驗的記錄,此時的記錄已經滿足了index key
的範圍,並且符合index filter
的條件,儲存引擎通過回表讀取了完整的記錄,判斷整條記錄是否滿足table filter
中的查詢條件,同樣的,若不滿足,跳過當前記錄,繼續讀取索引的下一條記錄,若滿足,則返回記錄,此記錄滿足了where的所有條件,可以返回給前端使用者.還是回到前面那條sql,where條件中的status=0就是table filter,因為status列並沒有新增索引,所以只能通過回表讀取該字段來過濾.
我們來總結下icp
的過程,mysql
把index filter
條件addtime>'1970'
下推到儲存引擎,儲存引擎根據addtime
索引來過濾掉不符合where
條件addtime>'1970'
的記錄,然後把最終資料返回給mysql server
,mysql server
再根據where
條件status=0
來做最後的過濾,最後把資料返回給使用者,這個過程減少了二次回表的次數,有效減少了磁碟io.最後我們來看下explain語句的結果:
MySql索引優化案例
建立新錶 create table article id int unsigned not null primary key auto increment,author id int unsigned not null,category id int unsigned not null,views ...
MySQL 索引優化案例
建表 create table article id int unsigned notnull primary keyauto increment author id int unsigned notnull category id int unsigned notnull views int un...
MySQL索引優化(索引三表優化案例)
建表sql phone book表建立索引 1 保證被驅動表的join欄位已經被索引 被驅動表 join 後的表為被驅動表 需要被查詢 2 left join 時,選擇小表作為驅動表,大表作為被驅動表。但是 left join 時一定是左邊是驅動表,右邊是被驅動表 3 inner join 時,my...