mysql using filesort Using temporary


using filesort 

一般人的回答是: “當行數據太大,導致內存無法容下這些數據產生的臨時表時,他們就會被放入磁盤中排序。”  很不幸,這個答案是錯的 ,臨時表在太大的時候確實會到磁盤離去,但是EXPLAIN不會顯示這些。

The truth is, filesort is badly named. Anytime a sort can’t be performed from an index, it’s a filesort. It has nothing to do with files. Filesort should be called “sort.” It is quicksort at heart.

那么事實是, filesort 這個名字取得太搓逼了。 filesort的意思是只要一個排序無法使用索引來排序,就叫filesort。他和file沒半毛錢關系。filesort應該叫做sort。(筆者補充一下:意思是說如果無法用已有index來排序,那么就需要數據庫服務器額外的進行數據排序,這樣其實是會增加性能開銷的。)

另外不光order by會出現filesort  group by沒有使用索引一樣會出現

檢查sort狀態

 show session status like '%sort%';  

 

sort_merge_passes  由於sort buffer不夠大,不得不將需要排序的數據進行分段,然后再通過sort merge的算法完成整個過程的merge總次數,一般整個參數用來參考sort buffer size 是否足夠。

sort range session/global級別(單位:次) 通過range scan完成的排序總次數。

sort rows   session/global 級別(單位:row) 排序的總行數。

sort scan   通過掃描表完成的排序總次數。

 

 

當無法避免排序操作時,又該如何來優化呢?很顯然,應該盡可能讓 MySQL 選擇使用第二種單路算法來進行排序。這樣可以減少大量的隨機IO操作,很大幅度地提高排序工作的效率。

1. 合理設置索引 讓排序字段使用上索引排序

2. 加大 max_length_for_sort_data 參數的設置

3. 去掉不必要的返回字段

當內存不是很充裕時,不能簡單地通過強行加大上面的參數來強迫 MySQL 去使用改進版的排序算法,否則可能會造成 MySQL 不得不將數據分成很多段,然后進行排序,這樣可能會得不償失。此時就須要去掉不必要的返回字段,讓返回結果長度適應 max_length_for_sort_data 參數的限制。

4. 增大 sort_buffer_size 參數設置

增大 sort_buffer_size 並不是為了讓 MySQL選擇改進版的排序算法,而是為了讓MySQL盡量減少在排序過程中對須要排序的數據進行分段,因為分段會造成 MySQL 不得不使用臨時表來進行交換排序。

 

Using temporary

內部臨時表產生的時機有以下幾種:

  • 使用 ORDER BY 子句和一個不一樣的 GROUP BY 子句(經過筆者實驗,應該是GROUP BY一個無索引列,就會產生臨時表),或者 ORDER BY 或 GROUP BY 的列不是來自JOIN語句序列的第一個表,就會產生臨時表(經筆者實驗,應該是使用JOIN時, GROUP BY 任何列都會產生臨時表)
  • DISTINCT 和 ORDER BY 一起使用時可能需要臨時表(筆者實驗是只要用了DISTINCT(非索引列),都會產生臨時表)
  • 用了 SQL_SMALL_RESULT, mysql就會用內存臨時表。定義:SQL_BIG_RESULT or SQL_SMALL_RESULT can be used with GROUP BY or DISTINCT to tell the optimizer that the result set has many rows or is small, respectively. For SQL_BIG_RESULT, MySQL

有些情況服務器會直接使用磁盤臨時表

  • 表里存在BLOB或者TEXT的時候(這是因為MEMORY引擎不支持這兩種數據類型,這里筆者補充一下,並非只要查詢里含有BLOB和TEXT類型的列就會產生磁盤臨時表,按照高性能MYSQL里的話,應該這么說:“Because the Memory storage engine doesn't support the BLOB and TEXT types, queries that use BLOB or TEXT columns and need an implicit temporary table will have to use on-disk MyISAM temporry tables, even for only a few rows.”也就是說如果我們的查詢中包含了BLOB和TEXT的列,而且又需要臨時表,這時候臨時表就被強制轉成使用磁盤臨時表,所以此書一直在提醒我們,如果要對BLOB和TEXT排序,應該使用SUBSTRING(column, length)將這些列截斷變成字符串,這樣就可以使用in-memory臨時表了
  • GROUP BY 或者 DISTINCT 子句大小超過 512 Bytes
  • 使用了UNION 或 UNION ALL 並且 SELECT 的列里有超過512 Bytes的列

 

如果內置內存臨時表創建后變得太大,MySQL會自動將它轉換成磁盤臨時表。內存臨時表的大小取決與 tmp_table_size參數和max_heap_table_size參數的值。用 CREATE TABLE 產生的內存臨時表的大小取決與 max_heap_table_size來決定是否要將其轉換成磁盤臨時表

當服務器生成一個內存臨時表,Created_tmp_tables狀態變量值會增加,當服務器創建了一個磁盤臨時表時,Created_tmp_disk_tables狀態變量值會增加。(這幾個變量可以通過 show status命令查看得到)

Tips: internal temporaray table 的大小受限制的是tmp_table_size和max_heap_table_size的最小值;而 user-created temporary table的大小只受限與max_heap_table_size,而與tmp_table_size無關


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM