由淺入深詳細說說mysql排序模式,怎麼影響mysql選擇不同的排序模式和怎麼優化排序。
排序是資料庫中的乙個基本功能,mysql也不例外。
使用者通過order by語句即能達到將指定的結果集排序的目的,其實不僅僅是order by語句,group by語句,distinct語句都會隱含使用排序。本文首先會簡單介紹sql如何利用索引避免排序代價,然後會介紹mysql實現排序的內部原理。
mysql在哪些地方會使用排序,怎麼判斷mysql使用了排序;
mysql有幾種排序模式,通過什麼方法讓mysql選擇不同的排序模式;
mysql排序跟read_rnd_buffer_size有啥關係,在哪些情況下增加read_rnd_buffer_size能優化排序;
怎麼判斷mysql使用到了磁碟來排序,怎麼避免或者優化磁碟排序;
排序時變長欄位(varchar)資料在記憶體是怎麼儲存的,5.7有哪些改進;
在情況下,排序模式有哪些改進;
sort_merge_pass到底是什麼 ,該狀態值過大說明了什麼問題,可以通過什麼方法解決;
mysql使用到了排序的話,依次可以通過什麼辦法分析和優化讓排序更快?
二、排序
我們通過explain檢視mysql執行計畫時,經常會看到在extra列中顯示using filesort。
對於不能利用索引避免排序的sql,資料庫不得不自己實現排序功能以滿足使用者需求,此時sql的執行計畫中會出現「using filesort」,這裡需要注意的是filesort並不意味著就是檔案排序,其實也有可能是記憶體排序,這個主要由sort_buffer_size引數與結果集大小確定。
其實這種情況就說明mysql使用了排序。using filesort經常出現在order by、group by、distinct、join等情況下。
mysql內部實現排序主要有3種方式,常規排序,優化排序和優先佇列排序。create table t1(id int, col1 varchar(64), col2 varchar(64), col3 varchar(64), primary key(id),key(col1,col2));select col1,col2,col3 from t1 where col1>100 order by col2;請看這三種排序的區別:
a.常規排序
(1).從表t1中獲取滿足where條件的記錄
(2).對於每條記錄,將記錄的主鍵+排序鍵(id,col2)取出放入sort buffer
(3).如果sort buffer可以存放所有滿足條件的(id,col2)對,則進行排序;否則sort buffer滿後,進行排序並固化到臨時檔案中。(排序演算法採用的是快速排序演算法)
(4).若排序中產生了臨時檔案,需要利用歸併排序演算法,保證臨時檔案中記錄是有序的
(5).迴圈執行上述過程,直到所有滿足條件的記錄全部參與排序
(6).掃瞄排好序的(id,col2)對,並利用id去撈取select需要返回的列(col1,col2,col3)
(7).將獲取的結果集返回給使用者。
從上述流程來看,是否使用檔案排序主要看sort buffer是否能容下需要排序的(id,col2)對,這個buffer的大小由sort_buffer_size引數控制。此外一次排序需要兩次io,一次是撈(id,col2),第二次是撈(col1,col2,col3),由於返回的結果集是按col2排序,因此id是亂序的,通過亂序的id去撈(col1,col2,col3)時會產生大量的隨機io。對於第二次mysql本身乙個優化,即在撈之前首先將id排序,並放入緩衝區,這個快取區大小由引數read_rnd_buffer_size控制,然後有序去撈記錄,將隨機io轉為順序io。
b.優化排序
常規排序方式除了排序本身,還需要額外兩次io。優化的排序方式相對於常規排序,減少了第二次io。主要區別在於,放入sort buffer不是(id,col2),而是(col1,col2,col3)。由於sort buffer中包含了查詢需要的所有字段,因此排序完成後可以直接返回,無需二次撈資料。這種方式的代價在於,同樣大小的sort buffer,能存放的(col1,col2,col3)數目要小於(id,col2),如果sort buffer不夠大,可能導致需要寫臨時檔案,造成額外的io。當然mysql提供了引數max_length_for_sort_data,只有當排序元組小於max_length_for_sort_data時,才能利用優化排序方式,否則只能用常規排序方式。
c.優先佇列排序
乙個最小堆的實現
如何實現最小堆,這是我按照書上寫的類以及定義的函式,那位大佬可以給我講一下如何在main函式中實現嗎?本人剛開始學習資料結構,如果有很低階的錯誤請擔待 類 pragma once include using namespace std class minheap typedef struct min...
排序 排序乙個棧(通過乙個輔助棧)
問題描述 現有乙個棧,包含一些整型的元素,現需要將此棧從頂到底按從大到小的順序排列 只允許申請乙個新棧 演算法實現 public void sortstackbystack stackstack help.push cur while help.isempty 演算法解析 1.申請乙個新棧,通過這兩...
mysql複製乙個空表 Mysql 複製乙個新錶
1 複製表結構及資料到新錶 create table 新錶 select from 舊表 這種方法會將oldtable中所有的內容都拷貝過來,當然我們可以用delete from newtable 來刪除。不過這種方法的乙個最不好的地方就是新錶中沒有了舊表的primary key extra aut...