mysql的排序優化
目錄
一、mysql的排序
當不能使用索引生成排序結果的時候,mysql需要自己進行排序。如果數據量小則在內存中進行,如果數據量大則需要使用磁盤,不過mysql將這個過程統一稱爲文件排序(filesort),即使完全是內存排序不需要任何磁盤文件時也是如此。
當排序的數據量小於“排序緩衝區”,使用內存進行“快速排序”操作;當內存不夠,mysql會先將數據分塊,對每個獨立的塊使用“快速排序”進行排序,並將各個塊的排序結果存放在磁盤上,然後將各個排序好的塊進行合併,最後返回排序結果。
二、排序 算法
1)兩次 傳輸排序 (舊版本使用)
讀取行指針和需要排序的字段,對其進行 排序,然後 再根據排序結果讀取所需要的數據行。
2)單次 傳輸排序 (新版本使用)
先讀取查詢所需要的所有列,然後再根據給定列進行排序,最後直接返回排序結果。
兩次 傳輸排序 | 單次 傳輸排序 | |
缺點 | 需要兩次數據傳輸,第二次讀取數據會產生大量的隨機I/O,成本高 | 產生更多的排序塊,佔用大量的空間 |
優點 | 排序時存儲儘可能少的數據,讓“排序緩衝區”中可以容納更多行進行排序 | 單次數據傳輸,不會產生隨機I/O |
所以,當查詢需要所有的列的總長度不超過參數max_length_for_sort_data時,mysql使用“單次傳輸排序”,這個參數我們是可以設置的。
三、關聯查詢的排序(分兩種情況)
1、當order by子句中的所有列都是來自關聯的第一個表,那麼mysql在關聯處理第一個表的時候就進行文件排序。通過explain可以查看到extra字段會有“using filesort”;
2、mysql會先將關聯的結果存放到一個臨時表中,然後等所有的關聯都結束後,再進行文件排序。extra字段是“using temporary;using filesort”。
另外,在5.6版本之前,如果查詢中有limit的話,也是在排序之後再進行limit,所以即使需要返回較少的數據,臨時表和需要排序的數據量仍然會非常大。在5.6版本之後,使用limit子句,會根據實際情況,選擇拋棄不滿足條件的結果,然後再進行排序。