SQL優化的步驟流程

原文鏈接:https://www.cnblogs.com/rouqinglangzi/p/11144960.html

一、優化SQL的方法

SQL優化的一般步驟:先查詢mysql數據庫運行狀況,然後定位慢查詢,再分析sql的執行過程,然後進行優化

1.使用show status查詢數據庫的運行狀況

//顯示數據庫運行狀態
SHOW STATUS
//顯示數據庫運行總時間
SHOW STATUS LIKE 'uptime'
//顯示連接的次數
SHOW STATUS LIKE 'connections'
//顯示執行CRUD的次數
SHOW STATUS LIKE 'com_select'
SHOW STATUS LIKE 'com_insert'
SHOW STATUS LIKE 'com_update'
SHOW STATUS LIKE 'com_delete'

2.定位慢查詢sql

我們可以通過mysql來記錄慢查詢,一旦有sql執行時間超過了設置的慢查詢時間,就會被記錄到慢查詢日誌中。這樣我們就可以從慢查詢日誌中定位慢查詢sql,然後進行分析優化。

查看慢查詢相關信息

//顯示慢查詢次數
SHOW STATUS LIKE 'slow_queries'
//顯示慢查詢時間,默認爲10s
SHOW VARIABLES LIKE 'long_query_time'

mysql的慢查詢默認是關閉的,可以通過修改配置文件或通過命令來開啓。

①修改配置文件方式

Linux下修改my.cnf,Windows下修改my.ini。修改後需要重啓mysql纔會生效。

#開啓慢查詢
slow-query-log=1
#慢查詢的文件路徑
slow_query_log_file="D:/Program Files/MySQL/Log/mysql-slow.log"
#慢查詢時間。默認爲10秒
long_query_time=10
複製代碼

②命令方式

也可以使用命令來修改。

【session級別】
#開啓慢查詢
SET slow_query_log='ON';

#設置慢查詢日誌存放位置
SET slow_query_log_file='/usr/local/mysql/data/slow.log';

#設置慢查詢時間
SET long_query_time=3

【global級別】
SET global slow_query_log='ON';
SET global slow_query_log_file='/usr/local/mysql/data/slow.log';
SET global long_query_time=3

3.分析慢查詢

在實際生產環境中,可能因爲開發寫了不正確的SQL語句,索引優化的不好,或其他查詢操作而導致數據庫整體性能下降。我們只需要分析一下慢查詢日誌就會知道問題出在哪。

//查看是否啓用慢日誌記錄和狀態
show variables like "%slow%"

如果慢查詢日誌中記錄內容較多,則可以使用Mysql自帶的慢查詢日誌分析工具mysqldumpslow工具來對慢查詢日誌進行分類彙總。該工具位於/mysql/bin目錄下。mysqldumpslow將會自動將文本完全一致但變量不同的SQL語句視爲同一個語句進行統計,變量值用N來代替。

mysqldumpslow -s r -t 10 /data/dbdata/frem-slow.log

424830-20190707081744320-989448386.png (1035Ã363)

4.使用explain分析sql執行過程

mysql會將慢查詢記錄到慢查詢日誌中,這時我們就可以針對這些慢查詢的sql進行分析和優化,需要用到explain命令。

explain [要分析的sql]

分析結果中有如下幾列:

+----+-------------+---------+------+---------------+------+---------+------+------+-------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+-------+

每列的含義如下。官方文檔:Explain Output Colums

  • simple:表示簡單查詢,join也是簡單查詢。(不包含union和子查詢)。
    #簡單查詢
    select id from emp;
    #簡單查詢(join)
    select id from emp join dept on emp.dept_id=dept.id;

     

  • primary:表示主查詢(最外層的查詢)。包括union操作的第一個select查詢。
    #子查詢形式:第一個select爲primary
    select * from app_school where id = (select id from app_school where id=100);
    
    #union形式:第一個select爲primary
    select * from app_school where id=100
    union
    select * from app_school where id=101;

     

  • subquery:表示子查詢(子查詢中的第一個select查詢)。
    #子查詢中的第1個select(即下面的第2個select)
    select * from app_school where id = (select id from app_school where id=100);

     

  • derived:表示導出表,from後跟着的子查詢。
    #from後的select屬於derived
    select * from (select id from app_school) t;

     

  • union:表示UNION操作的第2個或後面的查詢。
    #第2個select爲union
    select * from app_school where id=100
    union
    select * from app_school where id=101;

     

  • union result:表示獲取UNION最後結果的查詢。

 

我的總結:
①簡單查詢(包括join):simple
②子查詢:primary,subquery,derived
③union查詢:union,union result

 

③table:查詢的表。

④type:找到匹配行用到的訪問類型。

最爲常見的類型有system,const,eq_ref,ref,range,index,All

按照性能從高到低順序如下:

  • NULL:不用訪問表或索引,就可直接得出結果。
  • system:該表是最多僅有一行的系統表。(這是const類型的一個特例)
    系統表中的數據通常已經加載到了內存中,所以不需要磁盤IO。
    例子1:查詢系統表

    例子2:內層嵌套(const)返回了一個臨時表,外層嵌套從臨時表中查詢,其掃描類型也是system,也不需要磁盤IO。
  • const:最多隻有一個匹配行,所以該行中的其它列的值可以當作常量來處理。
                例如,根據主鍵primary key或唯一索引unique index進行查詢。
  • eq_ref:使用唯一索引,對於每個索引鍵值,表中只有一條記錄匹配。簡單說,就是多表連接中使用primary key或unique index作爲關聯條件。
  • ref:使用非唯一索引,或唯一索引的前綴掃描。
  • ref_or_null:與ref類似,區別在於條件中包含對NULL的查詢。
  • index_merge:索引合併優化。
  • unique_subquery:in的後面是一個查詢主鍵字段的子查詢。
  • index_subquery:與unique subquery類似,區別在於in的後面是查詢非唯一索引字段的子查詢。
  • range:只檢索指定範圍的行,使用一個索引來選擇行。常見於<,<=,>,>=,between或者IN操作符。
                 key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。
  • index:索引全掃描。遍歷整個索引來查詢匹配的行。
  • ALL:全表掃描,性能最差。

⑤possible_keys:表示查詢時可能使用到的索引

⑥key:表示實際使用的索引

⑦key_len:使用到的索引字段的長度

⑧ref:顯示該表的索引字段關聯了哪張表的哪個字段

⑨rows:掃描行的數量

⑩Extra:執行情況的說明和描述。包含不適合在其它列中顯示但對執行計劃非常重要的額外信息。

5.使用show profile分析sql

有時候,僅僅通過explain分析執行計劃並不能很快地定位SQL的問題,這時就可以選擇profile聯合分析。

Mysql從5.0.37開始增加了對show profiles和show profile語句的支持。默認profile是關閉的,可以通過set開啓session級別的profiling。

//查看是否支持profile
SELECT @@have_profiling
//開啓profile(session級別)
set profiling=1;

①執行select語句
②show profiles,查詢該sql語句的Query ID.
③通過show profile for query語句能看到執行中線程的每個狀態和消耗的時間。

show profile for query [上面的query id]

6.通過trace分析優化器如何選擇執行計劃

Mysql5.6提供了對sql的跟蹤trace,通過trace文件能夠進一步瞭解爲什麼優化器選擇A執行計劃而不選擇B執行計劃,幫助我們更好地理解優化器的行爲。

使用方式:
①首先打開trace,設置格式爲json,設置trace最大能夠使用的內存大小,避免解析過程中因爲默認內存過小而不能夠完整顯示。

//打開trace,設置json格式
SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
//設置內存
SET OPTIMIZER_TRACE_MAX_MEM_SIZE=1000000;

②接下來執行想做trace的sql語句

select xxx

③檢查INFORMATION_SCHEMA.OPTIMIZER_TRACE就知道mysql是如何執行sql的了

SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE \G

最後會輸出一個跟蹤文件。

7.確定問題並採用相應的優化措施

經過前面的一系列步驟,基本就可以確定問題出現的原因了。此時就可以根據情況採取相應的措施進行優化了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章