mysql> show create table test \G *************************** 1. row *************************** Table: test Create Table: CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `addtime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `a` int(11) unsigned NOT NULL, `b` int(11) unsigned NOT NULL, `c` int(11) unsigned NOT NULL, `data` varchar(20) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `u` (`addtime`,`a`,`b`), KEY `a` (`a`), KEY `b` (`b`), KEY `c` (`c`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8
執行查詢1 mysql> explain select * from test where addtime='2015-10-13 15:38:32' order by a , b ; +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ | 1 | SIMPLE | test | ref | u | u | 8 | const | 4 | Using where | +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ 執行查詢2 mysql> explain select * from test where addtime='2015-10-13 15:38:32' order by a , b ,c; +----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------------+ | 1 | SIMPLE | test | ref | u | u | 8 | const | 4 | Using where; Using filesort | +----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------------+ 使用filesort的情況 a、where語句與order by語句,使用了不同的索引 b、 檢查的行數過多,且沒有使用覆蓋索引 c、對索引列同時使用了ASC和DESC d、where語句或者ORDER BY語句中索引列使用了表達式,包括函數表達式 e、where 語句與ORDER BY語句組合滿足最左前綴,但where語句中使用了條件查詢 f、 當使用left join,使用右邊的表字段排序 2 利用內存/磁盤文件排序獲取結果 由於沒有可以利用的有序索引取得有序的數據,MySQL需要通過相應的排序算法,將取得的數據在sort_buffer_size系統變量所設置大小的排序區進行排序,這個排序區是每個Thread 獨享的,所以說可能在同一時刻在 MySQL 中可能存在多個 sort buffer 內存區域 MySQL中filesort 的實現算法有兩種: 1) 雙路排序:<sort_key, rowid> 是首先根據相應的條件取出相應的排序字段和可以直接定位行數據的行指針信息,然後在sort buffer 中進行排序(but this will be essentially hit the table in random order and is not very fast)。 2) 單路排序:是一次性取出滿足條件行的所有字段,然後在sort buffer中進行排序。 在 MySQL4.1 版本之前只有第一種排序算法,第二種算法是從MySQL4.1開始的改進算法,主要目的是為了減少第一次算法中需要兩次訪問表數據的IO操作,將兩次變成了一次,但相應也會耗用更多的 sort buffer 空間。典型的以空間換時間的優化方式。當然,MySQL4.1開始的以後所有版本同時也支持第一種算法 MySQL主要通過比較系統參數 max_length_for_sort_data的大小和Query語句所取出的字段類型大小總和來判定需要使用哪一種排序算法。如果max_length_for_sort_data更大,則使用第二種優化後的算法,反之使用第一種算法。所以如果希望 order BY 操作的效率盡可能的高,需要注意max_length_for_sort_data參數的設置。 3、使用Using temporary 臨時表來filesort 如果order by的子句只引用了聯接中的第一個表,MySQL會先對第一個表進行排序,然後進行聯接,expain中的Extra會出現Using Filesort 否則MySQL先把結果保存到臨時表(Temporary Table),然後再對臨時表的數據進行排序,此時expain中的Extra的顯示Using temporary Using Filesort 4、Join排序 mysql中有三種方式 1)、Use index-based access method that produces ordered output -》 null