在某些狀況中,MySQL能夠使用一個索引來知足ORDER BY子句,而不須要額外的排序。html
即便ORDER BY不確切匹配索引,只要WHERE子句中的全部未使用的索引部分和全部額外的ORDER BY 列爲常數,就能夠使用索引。下面的查詢使用索引來解決ORDER BY部分:mysql
注:key_part1,key_part2爲創建了索引的列web
SELECT * FROM t1算法
ORDER BY key_part1,key_part2,... ;sql
SELECT * FROM t1優化
WHERE key_part1=constantspa
ORDER BY key_part2;code
SELECT * FROM t1orm
ORDER BY key_part1 DESC, key_part2 DESC;htm
SELECT * FROM t1
WHERE key_part1=1
ORDER BY key_part1 DESC, key_part2 DESC;
在某些狀況下,MySQL不能使用索引來解決ORDER BY,儘管它仍然使用索引來找到匹配WHERE子句的行。這些狀況包括:
· 對不一樣的關鍵字使用ORDER BY:
· SELECT * FROM t1 ORDER BY key1, key2;
· 對關鍵字的非連續元素使用ORDER BY:
· SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
· 混合ASC和DESC:
· SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
· 用於查詢行的關鍵字與ORDER BY中所使用的不相同:
· SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
· 你正聯接許多表,而且ORDER BY中的列並非所有來自第1個用於搜索行的很是量表。(這是EXPLAIN輸出中的沒有const聯接類型的第1個表)。
· 有不一樣的ORDER BY和GROUP BY表達式。
· 使用的表索引的類型不能按順序保存行。例如,對於HEAP表的HASH索引狀況即如此。
經過EXPLAIN SELECT ...ORDER BY,能夠檢查MySQL是否能夠使用索引來解決查詢。若是Extra列內有Using filesort,則不能解決查詢。參見7.2.1節,「EXPLAIN語法(獲取關於SELECT的信息)」。
文件排序優化不只用於記錄排序關鍵字和行的位置,而且還記錄查詢須要的列。這樣能夠避免兩次讀取行。文件排序算法的工做象這樣:
1. 讀行匹配WHERE子句的行,如前面所示。
2. 對於每一個行,記錄構成排序關鍵字和行位置的一系列值,而且記錄查詢須要的列。
3. 根據排序關鍵字排序元組
4. 按排序的順序檢索行,但直接從排序的元組讀取須要的列,而不是再一次訪問表。
該算法比之前版本的Mysql有很大的改進。
爲了不速度變慢,該優化只用於排序元組中的extra列的總大小不超過max_length_for_sort_data系統變量值的時候。(將該變量設置得過高的的跡象是將看到硬盤活動太頻繁而CPU活動較低)。
若是想要增長ORDER BY的速度,首先看是否可讓MySQL使用索引而不是額外的排序階段。若是不能,能夠嘗試下面的策略:
· 增長sort_buffer_size變量的大小。
· 增長read_rnd_buffer_size變量的大小。
· 更改tmpdir指向具備大量空閒空間的專用文件系統。該選項接受幾個使用round-robin(循環)模式的路徑。在Unix中路徑應用冒號(‘:’)區間開,在Windows、NetWare和OS/2中用分號(‘;’)。能夠使用該特性將負載均分到幾個目錄中。註釋:路徑應爲位於不一樣物理硬盤上的文件系統的目錄,而不是同一硬盤的不一樣的分區。
默認狀況下,MySQL排序全部GROUP BY col1,col2,...查詢的方法如同在查詢中指定ORDER BY col1,col2,...。若是顯式包括一個包含相同的列的ORDER BY子句,MySQL能夠絕不減速地對它進行優化,儘管仍然進行排序。若是查詢包括GROUP BY但你想要避免排序結果的消耗,你能夠指定ORDER BY NULL禁止排序。例如:
INSERT INTO foo
SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;