看了網上很多排名很靠前的部落格,發現好多都講錯了!我開始按照部落格來,沒有懷疑,直到自己試了一下才發現是錯的。
file sort在面試中有時候會問到,這個其實挺能區分是不是真的瞭解order by的執行了。大部分人會以為file sort是檔案排
序,其實不要看字面意思,並不是檔案排序!只不過是表示排序沒有用到索引。其實不自己試驗,挺難想到的。
我這裡使用mysql5.7試驗了幾種情況,供大家參考.
首先建立的表欄位是 id, username, password, age, gender,其中id是自增的主鍵索引,(username, password, age)是聯合索引
1. 第一種情況:查詢語句不帶where條件過濾
1) select * from user_info order by username。使用了file sort,查詢的欄位不在username聯合索引中或者也不是主鍵id。會產生file sort。
等價於 select gender from user_info order by username,也會產生file sort!那 select id from user_info order by username,會不會產生file sort呢?是不會的,
因為mysql的b+樹葉子節點也是儲存了主鍵資訊的。
2)那這樣呢 select password from user_info order by username; 這個是不會產生file sort的!因為查詢的欄位在聯合索引中。
3) 上面兩種情況都是order by後面的欄位都是符合最左字首原則,沒有索引失效。沒有索引失效,是看查的欄位是不是在索引中!那索引失效會不會出現file sort呢?
select username from user_info order by password, username; //索引失效了
2. 第二種情況:查詢條件帶有where條件過濾
其實帶where條件也主要是看order by後面的欄位用的索引。如果order by後面的欄位不符合最左字首原則,那麼肯定是會產生file sort的。如果order by用到了索引
則看select 出來的欄位是否是在索引頁中儲存的資訊,如果是索引中的資訊則不會file sort。(這裡有幾個特殊情況,是mysql引擎的優化產生的)
1)select * from user_info where username = '1' order by username;
這個where條件是username,等值查詢。再去order by username。沒必要,所以mysql會把order by 去掉。order by都去掉了,肯定不會file sort了。
2)select age from user_info where age = '1' order by username;
這個是不會的,因為直接根據聯合索引去查詢 password = '1' 的,取出來的所有資料自然是根據username排序的(索引排好了序)。不需要file sort。
3) select gender from user_info where age = 1 order by username; 因為gender欄位不在order by使用的欄位中,所以需要file sort。
4)select password from user_info where password = '10' order by username, age;
首先看select出來的欄位在不在order by所使用的索引中,這個是在的。所以排除第一種情況。繼續分析。mysql先去這個索引中找出password 為 '10'的資料行,
極大情況有多條,在索引上取出的資料,看是不是符合先按username排序,再按age排序呢?是的,因為從索引上遍歷取password='10'的資料時候,取出來的
資料天然是按username先排序的(索引特性),password是等值的情況下,再按age排序的。所以取出來的資料已經排序了。
這一塊一定要注意啊!!!網上很多說mysql使用file sort看order by欄位有沒有符合最左匹配,是錯的!主要是看mysql在where條件上是否使用
索引(select (索引中的欄位)where 索引中的欄位),使用了索引的欄位,會using index去查出資料。然後再看是否取出來的資料是否是排好序的。
插曲,slect age from user_info where age = 1;會使用索引嗎?答案是會的,這個不符合最左字首匹配,但是select出來的欄位是在索引中的。
5)select password from user_info where age = 1 order by password, username;
這個是會用到索引的,因為select password的欄位在索引列中,並且where條件也是age也是在這個索引中的。
但是在B+樹索引上,根據age取出來的資料,看看是不是先password,再username排序呢?顯然不是,所以會發生file sort。
總結:什麼時候會發生file sort呢?
首先,看這個是不是走索引,是不是在索引上查詢資料。如果沒有使用索引,那麼會file sort。因為沒有在索引上取資料,那麼取出來的資料就是無序的。
需要file sort。如果使用了索引。取出來的資料看是否是滿足order by後面的排序欄位要求,如果滿足。則不需要file sort。如果不滿足,則需要file sort。