mysql - 產品數量多的時候, 如何通過mysql的slow query log來處置

 

mysql服務器在運行的時候會維護幾種日誌文件,或者說生成吧.Slow Query Log只是其中之一.它主要是記錄了執行時間超過一定時間(這個執行時間長短限額是mysql服務器的一個配置選項 - long_query_time)的SQL語句.以供開發人員或維護人員參考.要利用mysql的slow query log來解決問題,首先要知道它保存在哪裏?哪個配置可以開關這個日誌? 要打開mysql的slow query log開關,使之生成slow query log文件,可以向mysql的配置文件中(my.ini/my.cnf)添加如下配置

#To enable slow Query Log
log-slow-queries = /var/log/mysql/mysql-slow.log
long_query_time = 1

long_query_time配置選項設定了mysql服務器下sql語句執行的最長時間,超過這個時間的語句會被記錄到slow query log日誌文件中,但sql語句本身會繼續執行而不會終止. 

當然很多時候並沒有這個需要,只是需要優化網站的速度時才需要查看,平時則關閉以獲得最佳的性能.那麼你還可以通過使用啓動參數來臨時開啓這個功能.

 mysqld --log-slow-queries=[日誌文件路徑]

如果參數後面沒有指定日誌文件路徑,則會使用默認文件名,即主機名+-slow.log

首先需要說明的一點是,並不是這個日誌文件中出現的sql語句就一定有問題或寫的不對不好.只能說其中有一部分可以通過一些修改達到優化的目的.通常你可以針對符合下列條件的sql語句進行檢查,看看能不能優化.

A) "Rows_examined" 超過2000
B) "Rows_examined" 雖然小於2000,但是一秒內執行超過20次
C) "Rows_examined" 比"Rows_sent"的3倍還大

上面的三個條件只是一個簡單粗糙的標準,你要根據你的實際情況來確定.

 

首先應該針對符合條件的最壞的三到五條來檢查.一旦確定了SQL語句,你可以通過EXPLAIN語句來重構這些SQL語句.

grep Rows_examined tmp/mysql_slow_queries/20111120-23.log  | sort -g -k9 -r |head -5

# Query_time: 2.914175  Lock_time: 0.000268 Rows_sent: 10  Rows_examined: 28530
# Query_time: 2.804642  Lock_time: 0.000295 Rows_sent: 10  Rows_examined: 28530
# Query_time: 6.682182  Lock_time: 0.205899 Rows_sent: 16  Rows_examined: 392
# Query_time: 1.579871  Lock_time: 0.000148 Rows_sent: 325  Rows_examined: 325
# Query_time: 2.669462  Lock_time: 0.728236 Rows_sent: 0  Rows_examined: 1

然後找出它所對應的SQL語句# Query_time: 6.379132  Lock_time: 0.265194 Rows_sent: 11  Rows_examined: 10551

grep -A 1 -B 2 10551 tmp/mysql_slow_queries/20111120-23.log

# Mon Nov 21 00:07:55 2011
# Query_time: 2.914175  Lock_time: 0.000268 Rows_sent: 10  Rows_examined: 28530
use xxxxxxxx;
SELECT 1 AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`, `e`.`name`, `e`.`short_description`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`, `e`.`news_to_date`, `e`.`url_key`, `e`.`required_options`, `e`.`image_label`, `e`.`small_image_label`, `e`.`thumbnail_label`, `e`.`created_at`, `e`.`msrp_enabled`, `e`.`msrp_display_actual_price_type`, `e`.`msrp`, `e`.`tax_class_id`, `e`.`price_type`, `e`.`weight_type`, `e`.`price_view`, `e`.`shipment_type`, `e`.`links_purchased_separately`, `e`.`links_exist`, `e`.`is_imported`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `cat_index`.`position` AS `cat_index_position` FROM `catalog_product_flat_1` AS `e`
 INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id='1' AND cat_index.visibility IN(2, 4) AND cat_index.category_id='2' ORDER BY rand() ASC LIMIT 10

--
# Mon Nov 21 00:52:51 2011
# Query_time: 2.804642  Lock_time: 0.000295 Rows_sent: 10  Rows_examined: 28530
use xxxxxxxx;
SELECT 1 AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`, `e`.`name`, `e`.`short_description`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`, `e`.`news_to_date`, `e`.`url_key`, `e`.`required_options`, `e`.`image_label`, `e`.`small_image_label`, `e`.`thumbnail_label`, `e`.`created_at`, `e`.`msrp_enabled`, `e`.`msrp_display_actual_price_type`, `e`.`msrp`, `e`.`tax_class_id`, `e`.`price_type`, `e`.`weight_type`, `e`.`price_view`, `e`.`shipment_type`, `e`.`links_purchased_separately`, `e`.`links_exist`, `e`.`is_imported`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `cat_index`.`position` AS `cat_index_position` FROM `catalog_product_flat_1` AS `e`
 INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id='1' AND cat_index.visibility IN(2, 4) AND cat_index.category_id='2' ORDER BY rand() ASC LIMIT 10

 

當然你有可能只會輸出一條語句,這個時候你需要確定一下是哪個數據庫,你可以通過下面的這條命令

grep -A 1 -B 10000 28530 tmp/mysql_slow_queries/20111120-23.log|grep -i ^use |tail -1 

 

確定了數據庫,你可以通過mysql控制檯,使用EXPLAIN語句來分析對應的SQL語句,通過EXPLAIN的執行結果分析,看哪個表需要改進.通常是通過索引來改進一個查詢的效率.當然具體的EXPLAIN的使用需要查詢手冊進一步瞭解.

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