1. 程式人生 > >mysql 優化之開啟慢查詢日誌並分析原因

mysql 優化之開啟慢查詢日誌並分析原因

轉載:https://blog.csdn.net/haiqiao_2010/article/details/25138099

第一步.開啟mysql慢查詢

方式一:修改配置檔案

Windows:Windows 的配置檔案為 my.ini,一般在 MySQL 的安裝目錄下或者 c:\Windows 下。

Linux:Linux 的配置檔案為 my.cnf ,一般在 /etc 下

在 my.ini 增加幾行:

  1. [mysqlld]
  2. long_query_time=2
  3. #5.0、5.1等版本配置如下選項
  4. log-slow-queries="mysql_slow_query.log"
  5. #5.5及以上版本配置如下選項
  6. slow-query-log=On
  7. slow_query_log_file="mysql_slow_query.log"
  8. log-query-not-using-indexes

     第一句使用來定義查過多少秒的查詢算是慢查詢,我這裡定義的是2秒

第二句使用來定義慢查詢日誌的路徑(因為是windows,所以不牽涉許可權問題)

第三句就是記錄下沒有使用索引的query

第二步:檢視關於慢查詢的狀態

方式二:通過MySQL資料庫開啟慢查詢

上文的配置需要重啟mysql server程序mysqld才會生效。但是很多時候,尤其是產品運營環境,不希望每次修改都需要重新啟動mysql伺服器,也希望能在某些特定時間記 錄。MySQL5.1給我們提供了更為靈活的執行時控制,使得你不必重新啟動mysql伺服器,也能選擇性地記錄或者不記錄某些slow queries。

MySQL5.1中,提供了全域性變數slow_query_log、slow_query_log_file可以靈活地控制enable/disable慢查詢。同時可以通過long_query_time設定時間
#//啟用slow query記錄
#注意:設定了slow_query_log全域性變數, log_slow_queries也會隱性地跟著改變
mysql>set global slow_query_log=ON

不幸運的是,在MySQL5.0並沒有提供類似的全域性變數來靈活控制,但是我們可以通過將long_query_time設定得足夠大來避免記錄某些查詢語句。比如
mysql>set global long_query_time = 3600;

mysql>set global log_querise_not_using_indexes = ON;

MySQL5.0, 不關服務的情況下,希望不記錄日誌的辦法是將日誌檔案成為/dev/null的符號連結(symbolic link)。注意:你只需要在改變後執行FLUSH LOGS以確定MYSQL釋放當前的日誌檔案描述符,重新把日誌記錄到/dev/null

和MySQL5.0不同,MySQL5.1可以在執行時改變日記行為,將日誌記錄到資料庫表中。只要將mysql全域性變數log_output設定為 TABLE即可。MySQL會將日誌分別記錄到表mysql.gengera_log和mysql.slow_log二張表中。但是,我們推薦將日誌記錄 在日記檔案中。
mysql> show variables like ‘log_output’\G
Variable_name: log_output
Value: FILE
mysql>set global log_output=’table’;
缺陷與審記

雖然記錄了slow query能夠幫助你優化產品。但是MySQL目前版本,還有幾大蹩足的地方。
1.MySQL5.0版本, long_query_time時間粒度不夠細,最小值為1秒。對於高併發效能的網頁尾本而言,1秒出現的意義不大。即出現1秒的查詢比較少。直到mysql5.1.21才提供更細粒度的long_query_time設定.
2.不能將伺服器執行的所有查詢記錄到慢速日誌中。雖然MySQL普通日誌記錄了所有查詢,但是它們是解析查詢之前就記錄下來了。這意味著普通日誌沒辦法包含諸如執行時間,鎖表時間,檢查行數等資訊。
3.如果開啟了log_queries_not_using_indexes選項,slow query日誌會充滿過多的垃圾日誌記錄,這些快且高效的全表掃描查詢(表小)會沖掉真正有用的slow queries記錄。比如select * from category這樣的查詢也會被記錄下來。

通過microslow-patch補丁可使用更細的時間粒度,和記錄所有執行過的sql語句。不過,使用這個補訂不得不自己編譯MySQL,出於穩定性考濾,我們推薦在開發測試環境,可以打上這個補丁,享受這個補丁帶來的便利。在運營環境儘量不要這麼做…

   第二步.驗證慢查詢是否開啟

執行如下SQL語句來檢視mysql慢查詢的狀態
執行結果會把是否開啟慢查詢、慢查詢的秒數、慢查詢日誌等資訊列印在螢幕上。
  1. /*檢視慢查詢時間 */
  2. show variables like "long_query_time";預設10s
  3. /*檢視慢查詢配置情況 */
  4. show status like "%slow_queries%";
  5. /*檢視慢查詢日誌路徑 */
  6. show variables like "%slow%";

第三步:執行一次慢查詢操作

其實想要執行一次有實際意義的慢查詢比較困難,因為在自己測試的時候,就算查詢有20萬條資料的海量表,也只需要0.幾秒。我們可以通過如下語句代替:
SELECT SLEEP(10);
第四步:檢視慢查詢的數量
通過如下sql語句,來檢視一共執行過幾次慢查詢:
show global status like '%slow%';

mysql日誌的配置:

  1. 注意:這些日檔案在mysql重啟的時候才會生成
  2. #記錄所有sql語句
  3. log=E:/mysqllog/mysql.log
  4. #記錄資料庫啟動關閉資訊,以及執行過程中產生的錯誤資訊
  5. log-error=E:/mysqllog/myerror.log
  6. # 記錄除 select語句之外的所有 sql語句到日誌中,可以用來恢復資料檔案
  7. log- bin=E:/mysqllog/ bin
  8. #記錄查詢慢的 sql語句
  9. log-slow-queries=E:/mysqllog/slow.log
  10. #慢查詢時間
  11. long_query_time= 2


   第四步:分析慢查詢日誌

方式一:通過工具分析

MySQL自帶了mysqldumpslow工具用來分析slow query日誌,除此之外,還有一些好用的開源工具。比如MyProfi(下載地址:http://sourceforge.net/projects/myprofi/)、mysql-log-filter,當然還有mysqlsla

以下是mysqldumpslow常用引數說明,詳細的可應用mysqldumpslow -help查詢。

    -s,是表示按照何種方式排序,c、t、l、r分別是按照記錄次數、時間、查詢時間、返回的記錄數來排序(從大到小),ac、at、al、ar表示相應的倒敘。 
-t,是top n的意思,即為返回前面多少條資料。
-g,後邊可以寫一個正則匹配模式,大小寫不敏感。


接下來就是用mysql自帶的慢查詢工具mysqldumpslow分析了(mysql的bin目錄下),我這裡的日誌檔名字是host-slow.log。

列出記錄次數最多的10個sql語句

mysqldumpslow -s c -t 10 host-slow.log

列出返回記錄集最多的10個sql語句

mysqldumpslow -s r -t 10 host-slow.log

按照時間返回前10條裡面含有左連線的sql語句

mysqldumpslow -s t -t 10 -g "left join" host-slow.log

使用mysqldumpslow命令可以非常明確的得到各種我們需要的查詢語句,對MySQL查詢語句的監控、分析、優化起到非常大的幫助。

方式二:直接分析mysql慢查詢日誌

日誌部分內容如下:

# Time: 121017 17:38:54 
# [email protected]: root[root] @ localhost [127.0.0.1] 
Query_time: 3.794217 Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 4194304 
SET timestamp=1350466734; 
select * from wei where text='orange'; 
# Time: 121017 17:46:22 
# [email protected]: root[root] @ localhost [127.0.0.1] 
Query_time: 3.819219  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 4194304 
SET timestamp=1350467182; 
select * from wei where text='xishizhaohua'; 

其實定位到了慢查詢語句就已經完成了一大不了,執行explain或者desc命令檢視慢查詢語句,如下圖:

 

問題很明顯,解決方式也很明顯,建索引了。

  1. mysql> create index text_index on wei( text);
  2. Query OK, 4194304 rows affected (1 min 58.07 sec)
  3. Records: 4194304 Duplicates: 0 Warnings: 0

然後在執行查詢操作,用時明顯少了很多。

  1. mysql> select * from wei where text= 'orange';
  2. + ---------+--------+
  3. | id | text |
  4. + ---------+--------+
  5. | 4103519 | orange |
  6. + ---------+--------+
  7. 1 row in set ( 0.33 sec)

Slow Query日誌,雖然幫助你記錄了那些執行過了的SQL語句。但它不是萬能的,意義可能沒有你想象的那麼大。它只告訴了你哪些語句慢,但是為什麼慢?具體 原因,還是需要你自己去分析,不斷的除錯。也許,你只需要換一條更有效的sql語句,也許你只需簡單地增加一個索引,但也有可能你需要調整你應用程式的設 計方案。比如,上面那條語句是很明顯,它檢查了600多萬行資料。不幸的是,並不是每條語句都這麼明顯。也許還有別的原因,比如:
*鎖表了,導致查詢處於等態狀態。lock_time顯示了查詢等待鎖被翻譯的時間
*資料或索引沒有被快取。常見於第一次啟動伺服器或者伺服器沒有調優
*備份資料庫,I/O變慢
*也許同時運行了其它的查詢,減少了當前查詢

所以,不要過於緊張日誌檔案某條記錄,而應該理性地審記,找出真正的原因。如果經常出現的slow query需要特別注意。如果個別出現,則做一些常規檢查即可。我們建議,統計並且形成基準報告,進行比較排除,比胡亂瞎撞有用。希望大家不要在這部分過於浪費時間與精力。


轉載:https://blog.csdn.net/haiqiao_2010/article/details/25138099

第一步.開啟mysql慢查詢

方式一:修改配置檔案

Windows:Windows 的配置檔案為 my.ini,一般在 MySQL 的安裝目錄下或者 c:\Windows 下。

Linux:Linux 的配置檔案為 my.cnf ,一般在 /etc 下

在 my.ini 增加幾行:

  1. [mysqlld]
  2. long_query_time=2
  3. #5.0、5.1等版本配置如下選項
  4. log-slow-queries="mysql_slow_query.log"
  5. #5.5及以上版本配置如下選項
  6. slow-query-log=On
  7. slow_query_log_file="mysql_slow_query.log"
  8. log-query-not-using-indexes

     第一句使用來定義查過多少秒的查詢算是慢查詢,我這裡定義的是2秒

第二句使用來定義慢查詢日誌的路徑(因為是windows,所以不牽涉許可權問題)

第三句就是記錄下沒有使用索引的query

第二步:檢視關於慢查詢的狀態

方式二:通過MySQL資料庫開啟慢查詢

上文的配置需要重啟mysql server程序mysqld才會生效。但是很多時候,尤其是產品運營環境,不希望每次修改都需要重新啟動mysql伺服器,也希望能在某些特定時間記 錄。MySQL5.1給我們提供了更為靈活的執行時控制,使得你不必重新啟動mysql伺服器,也能選擇性地記錄或者不記錄某些slow queries。

MySQL5.1中,提供了全域性變數slow_query_log、slow_query_log_file可以靈活地控制enable/disable慢查詢。同時可以通過long_query_time設定時間
#//啟用slow query記錄
#注意:設定了slow_query_log全域性變數, log_slow_queries也會隱性地跟著改變
mysql>set global slow_query_log=ON

不幸運的是,在MySQL5.0並沒有提供類似的全域性變數來靈活控制,但是我們可以通過將long_query_time設定得足夠大來避免記錄某些查詢語句。比如
mysql>set global long_query_time = 3600;

mysql>set global log_querise_not_using_indexes = ON;

MySQL5.0, 不關服務的情況下,希望不記錄日誌的辦法是將日誌檔案成為/dev/null的符號連結(symbolic link)。注意:你只需要在改變後執行FLUSH LOGS以確定MYSQL釋放當前的日誌檔案描述符,重新把日誌記錄到/dev/null

和MySQL5.0不同,MySQL5.1可以在執行時改變日記行為,將日誌記錄到資料庫表中。只要將mysql全域性變數log_output設定為 TABLE即可。MySQL會將日誌分別記錄到表mysql.gengera_log和mysql.slow_log二張表中。但是,我們推薦將日誌記錄 在日記檔案中。
mysql> show variables like ‘log_output’\G
Variable_name: log_output
Value: FILE
mysql>set global log_output=’table’;
缺陷與審記

雖然記錄了slow query能夠幫助你優化產品。但是MySQL目前版本,還有幾大蹩足的地方。
1.MySQL5.0版本, long_query_time時間粒度不夠細,最小值為1秒。對於高併發效能的網頁尾本而言,1秒出現的意義不大。即出現1秒的查詢比較少。直到mysql5.1.21才提供更細粒度的long_query_time設定.
2.不能將伺服器執行的所有查詢記錄到慢速日誌中。雖然MySQL普通日誌記錄了所有查詢,但是它們是解析查詢之前就記錄下來了。這意味著普通日誌沒辦法包含諸如執行時間,鎖表時間,檢查行數等資訊。
3.如果開啟了log_queries_not_using_indexes選項,slow query日誌會充滿過多的垃圾日誌記錄,這些快且高效的全表掃描查詢(表小)會沖掉真正有用的slow queries記錄。比如select * from category這樣的查詢也會被記錄下來。

通過microslow-patch補丁可使用更細的時間粒度,和記錄所有執行過的sql語句。不過,使用這個補訂不得不自己編譯MySQL,出於穩定性考濾,我們推薦在開發測試環境,可以打上這個補丁,享受這個補丁帶來的便利。在運營環境儘量不要這麼做…

   第二步.驗證慢查詢是否開啟

執行如下SQL語句來檢視mysql慢查詢的狀態
執行結果會把是否開啟慢查詢、慢查詢的秒數、慢查詢日誌等資訊列印在螢幕上。
  1. /*檢視慢查詢時間 */
  2. show variables like "long_query_time";預設10s
  3. /*檢視慢查詢配置情況 */
  4. show status like "%slow_queries%";
  5. /*檢視慢查詢日誌路徑 */
  6. show variables like "%slow%";

第三步:執行一次慢查詢操作

其實想要執行一次有實際意義的慢查詢比較困難,因為在自己測試的時候,就算查詢有20萬條資料的海量表,也只需要0.幾秒。我們可以通過如下語句代替:
SELECT SLEEP(10);
第四步:檢視慢查詢的數量
通過如下sql語句,來檢視一共執行過幾次慢查詢:
show global status like '%slow%';

mysql日誌的配置:

  1. 注意:這些日檔案在mysql重啟的時候才會生成
  2. #記錄所有sql語句
  3. log=E:/mysqllog/mysql.log
  4. #記錄資料庫啟動關閉資訊,以及執行過程中產生的錯誤資訊
  5. log-error=E:/mysqllog/myerror.log
  6. # 記錄除 select語句之外的所有 sql語句到日誌中,可以用來恢復資料檔案
  7. log- bin=E:/mysqllog/ bin
  8. #記錄查詢慢的 sql語句
  9. log-slow-queries=E:/mysqllog/slow.log
  10. #慢查詢時間
  11. long_query_time= 2


   第四步:分析慢查詢日誌

方式一:通過工具分析

MySQL自帶了mysqldumpslow工具用來分析slow query日誌,除此之外,還有一些好用的開源工具。比如MyProfi(下載地址:http://sourceforge.net/projects/myprofi/)、mysql-log-filter,當然還有mysqlsla

以下是mysqldumpslow常用引數說明,詳細的可應用mysqldumpslow -help查詢。

    -s,是表示按照何種方式排序,c、t、l、r分別是按照記錄次數、時間、查詢時間、返回的記錄數來排序(從大到小),ac、at、al、ar表示相應的倒敘。 
-t,是top n的意思,即為返回前面多少條資料。
-g,後邊可以寫一個正則匹配模式,大小寫不敏感。


接下來就是用mysql自帶的慢查詢工具mysqldumpslow分析了(mysql的bin目錄下),我這裡的日誌檔名字是host-slow.log。

列出記錄次數最多的10個sql語句

mysqldumpslow -s c -t 10 host-slow.log

列出返回記錄集最多的10個sql語句

mysqldumpslow -s r -t 10 host-slow.log

按照時間返回前10條裡面含有左連線的sql語句

mysqldumpslow -s t -t 10 -g "left join" host-slow.log

使用mysqldumpslow命令可以非常明確的得到各種我們需要的查詢語句,對MySQL查詢語句的監控、分析、優化起到非常大的幫助。

方式二:直接分析mysql慢查詢日誌

日誌部分內容如下:

# Time: 121017 17:38:54 
# [email protected]: root[root] @ localhost [127.0.0.1] 
Query_time: 3.794217 Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 4194304 
SET timestamp=1350466734; 
select * from wei where text='orange'; 
# Time: 121017 17:46:22 
# [email protected]: root[root] @ localhost [127.0.0.1] 
Query_time: 3.819219  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 4194304 
SET timestamp=1350467182; 
select * from wei where text='xishizhaohua'; 

其實定位到了慢查詢語句就已經完成了一大不了,執行explain或者desc命令檢視慢查詢語句,如下圖:

 

問題很明顯,解決方式也很明顯,建索引了。

  1. mysql> create index text_index on wei( text);
  2. Query OK, 4194304 rows affected (1 min 58.07 sec)
  3. Records: 4194304 Duplicates: 0 Warnings: 0

然後在執行查詢操作,用時明顯少了很多。

  1. mysql> select * from wei where text= 'orange';
  2. + ---------+--------+
  3. | id | text |
  4. + ---------+--------+
  5. | 4103519 | orange |
  6. + ---------+--------+
  7. 1 row in set ( 0.33 sec)

Slow Query日誌,雖然幫助你記錄了那些執行過了的SQL語句。但它不是萬能的,意義可能沒有你想象的那麼大。它只告訴了你哪些語句慢,但是為什麼慢?具體 原因,還是需要你自己去分析,不斷的除錯。也許,你只需要換一條更有效的sql語句,也許你只需簡單地增加一個索引,但也有可能你需要調整你應用程式的設 計方案。比如,上面那條語句是很明顯,它檢查了600多萬行資料。不幸的是,並不是每條語句都這麼明顯。也許還有別的原因,比如:
*鎖表了,導致查詢處於等態狀態。lock_time顯示了查詢等待鎖被翻譯的時間
*資料或索引沒有被快取。常見於第一次啟動伺服器或者伺服器沒有調優
*備份資料庫,I/O變慢
*也許同時運行了其它的查詢,減少了當前查詢

所以,不要過於緊張日誌檔案某條記錄,而應該理性地審記,找出真正的原因。如果經常出現的slow query需要特別注意。如果個別出現,則做一些常規檢查即可。我們建議,統計並且形成基準報告,進行比較排除,比胡亂瞎撞有用。希望大家不要在這部分過於浪費時間與精力。