最近常常碰到網站慢的情況,登陸到後臺,查詢一下 /opt/mysql/bin/mysqladmin processlist;
發現一個查詢狀態爲: Copying to tmp table 而且此查詢速度非常慢,基本一分鐘左右纔出來,後面是很多查詢,狀態爲lock。
用命令殺掉此查詢 /opt/mysql/bin/mysqladmin kill 進程號;
後面的查詢一下子都好了。 ok, 找到了問題的原因,此查詢效率太低。問一下程序員,找來此查詢的代碼,用工具進行一下簡單分析。
(說明:這裏是我不喜歡mysql的原因之一,mysql我不知道從哪裏能看到內存正在執行哪些sql,以及完整的sql是什麼。)
explain
SELECT a.* , IF(b.`gid` IS NULL , 0, SUM( b.`mark` )) AS `score` ,
IF(c.`b_times` IS NULL ,0, c.`b_times`) AS `day_b_times`
FROM `league_info` AS a LEFT JOIN `mark_logs` AS b ON b.`day_date` = '2006-03-22'
AND b.`gid` = a.`id` LEFT JOIN `visit_stat` AS c ON c.`stat_id` = a.`id` AND c.`type` = 'league'
AND c.`day`='2006_03_22' WHERE a.`validate`='1' GROUP BY a.`id`
ORDER BY day_b_times DESC, a.`id`;
+----+-------------+-------+------+-------------------------------+------------------+---------+---------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------------+------------------+---------+---------------------+------+----------------------------------------------+
| 1 | SIMPLE | a | ref | league_info_idx4 | league_info_idx4 | 1 | const | 1441 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | b | ref | mark_logs_idx1,mark_logs_idx2 | mark_logs_idx1 | 4 | new5jia1.a.id | 56 | |
| 1 | SIMPLE | c | ref | visit_stat_idx1 | visit_stat_idx1 | 26 | new5jia1.a.id,const | 10 | |
+----+-------------+-------+------+-------------------------------+------------------+---------+---------------------+------+----------------------------------------------+
看了一下,其實此查詢嵌套用得不好,作爲程序員應該儘量避免用 not in ,in, left join ,right join 等等,不過這些不歸我管,我只能提一些建議。
(順便說一聲:oracle裏面可以用 exist ,not exist, minus等代替in ,not in 效率高出很多 )
此分析對我沒有太大的作用,因此用google查詢了一下,發現網上一篇文章講得很好,
( http://clay111.blogchina.com/4721079.html 我給轉貼了,感興趣可以看看)
Copying to tmp table on disk The temporary result set was larger than tmp_table_size and the
thread is now changing the in memory-based temporary table to a disk based one to save memory.
哦,原來是這樣的,如果查詢超出了tmp_table_size的限制,那麼mysql用/tmp保存查詢結果,然後返回給客戶端。
set global tmp_table_size=209715200 (200M)
再次運行此查詢,用/opt/mysql/bin/mysqladmin processlist; 進行觀察,發現不會出現上述問題.
至此問題解決.
調節tmp_table_size 的時候發現另外一些參數
Qcache_queries_in_cache 在緩存中已註冊的查詢數目
Qcache_inserts 被加入到緩存中的查詢數目
Qcache_hits 緩存採樣數數目
Qcache_lowmem_prunes 因爲缺少內存而被從緩存中刪除的查詢數目
Qcache_not_cached 沒有被緩存的查詢數目 (不能被緩存的,或由於 QUERY_CACHE_TYPE)
Qcache_free_memory 查詢緩存的空閒內存總數
Qcache_free_blocks 查詢緩存中的空閒內存塊的數目
Qcache_total_blocks 查詢緩存中的塊的總數目
Qcache_free_memory 可以緩存一些常用的查詢,如果是常用的sql會被裝載到內存。那樣會增加數據庫訪問速度。
mysql查詢慢(Copying to tmp table)解決一例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.