網站運行的慢了,查找原因是Copying to tmp table on disk那怎么解決這個問題呢
解決一例最近常常碰到網站慢的情況,登陸到后臺,查詢一下 /opt/mysql/bin/mysqladmin processlist;
發現一個查詢狀態為: Copying to tmp table 而且此查詢速度非常慢,基本一分鐘左右才出來,后面是很多查詢,狀態為lock。
此分析對我沒有太大的作用,因此用google查詢了一下,發現網上一篇文章講得很好: 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 on disk占用了很長的執行時間,如下性能分析圖:
上圖中的第一行顯示mysql向臨時表復制數據花費了117毫秒的時間,這個必須想辦法優化掉。
經過查資料發現mysql可以通過變量tmp_table_size和max_heap_table_size來控制內存表大小上限,如果超過上限會將數據寫到磁盤上,從而會有物理磁盤的讀寫操作,導致影響性能。
我們可以通過調整這兩個變量的值來提升性能(當然前提條件是mysql所在服務器有足夠的內存)。
首先可以通過下面語句查看當前的變量值:
SHOW VARIABLES LIKE'max_heap_table_size%';
然后通過SET GLOBAL max_heap_table_size=522715200;?設置變量值為512M,你可以根據自己的情況設置合適的值;tmp_table_size變量的設置方法一樣。
在使用mysql是提醒mysql Copying to tmp table on disk 錯誤了,下面我們來看看此問題的解決辦法.
經過查資料發現mysql可以通過變量tmp_table_size和max_heap_table_size來控制內存表大小上限,如果超過上限會將數據寫到磁盤上,從而會有物理磁盤的讀寫操作,導致影響性能.
我們可以通過調整這兩個變量的值來提升性能,當然前提條件是mysql所在服務器有足夠的內存.
首先可以通過下面語句查看當前的變量值:
SHOW VARIABLES LIKE ‘max_heap_table_size%’;
然后通過SET GLOBAL max_heap_table_size=522715200; 設置變量值為512M,你可以根據自己的情況設置合適的值,tmp_table_size變量的設置方法一樣.
SHOW VARIABLES LIKE ‘tmp_table_size’;
SET GLOBAL max_heap_table_size=512*1024*1024;
其次發現開發人員編寫的語句,根本無法使用到緩存,這個sql優化是個長期的過程,代碼如下:
#?Time:?140901?16:26:23
#?User@Host:?wealth[wealth]?@?[172.20.1.70]
#?Query_time:?2266.887211?Lock_time:?0.000196?Rows_sent:?17?Rows_examined:?71501657
SET?timestamp=1409559983;
SELECT?a.Pid,count(a.id)ascount,p.ProductId,p.ProductName,p.ProductType,p.Profit,p.StartTime,p.EndTime,p.StartMoney,p.AddTime,i.IssuerName?FROM?`Issuer`asi,`Count`asa?left?join?Productasp?on?a.Pid=p.ProductId?WHERE?a.Stime?>?‘time()?–?3600*24*30′andp.IssuerId=i.IssuerId?AND?p.IsDel=0?group?by?a.Pid?order?bycount(a.id)?desc?limit?0,17;