排序操作是非常消耗cpu的操作,當系統設置不當或query取出的字段過多時,還可以造成MySQL不得不放棄優化後的排序算法,而使用較為古老的需要兩次IO的讀取表數據的排序算法,使排序效率非常低下。
利用索引進行排序操作,主要是利用了索引的有序性。在通過索引進行檢索的過程中,就已經得到了有序的數據訪問順序,依次讀取結果數據後就不需要進行排序操作,進而避免了此操作,提高了排序結果集的query性能。
很簡單,盡量使用索引排序,這就對了。
做個實驗,表結構如下
mysql> show create table artist \G
*************************** 1. row ***************************
Table: artist
Create Table: CREATE TABLE `artist` (
`artist_id` int(10) unsigned NOT NULL,
`type` enum('Band','Person','Unknown','Combination') NOT NULL,
`name` varchar(255) NOT NULL,
`gender` enum('Male','Female') DEFAULT NULL,
`founded` year(4) DEFAULT NULL,
`country_id` smallint(5) unsigned DEFAULT NULL,
PRIMARY KEY (`artist_id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)mysql> Explain select name, founded from artist where name like 'AUSTRALIA%' order by founded \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: artist
type: range
possible_keys: name
key: name
key_len: 257
ref: NULL
rows: 22
Extra: Using index condition; Using filesort
1 row in set (0.00 sec)mysql> show session status like '%sort%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Sort_merge_passes | 0 | | Sort_range | 0 | | Sort_rows | 0 | | Sort_scan | 0 | +-------------------+-------+ 4 rows in set (0.00 sec) mysql> select name, founded from artist where name like 'AUSTRALIA%' order by founded \G ...... 22 rows in set (0.00 sec) mysql> show session status like '%sort%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Sort_merge_passes | 0 | | Sort_range | 1 | | Sort_rows | 22 | | Sort_scan | 0 | +-------------------+-------+ 4 rows in set (0.00 sec)
幾個參數
sort_merge_passes 由於sort buffer不夠大,不得不將需要排序的數據進行分段,然後再通過sort merge的算法完成整個過程的merge總次數,一般整個參數用來參考sort buffer size 是否足夠。
sort range session/global級別(單位:次) 通過range scan完成的排序總次數。
sort rows session/global 級別(單位:row) 排序的總行數。
sort scan 通過掃描表完成的排序總次數。
索引排序,其中extra中的filesort不見了
mysql> Explain select name, founded from artist where name like 'AUSTRALIA%' order by name \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: artist
type: range
possible_keys: name
key: name
key_len: 257
ref: NULL
rows: 22
Extra: Using index condition
1 row in set (0.00 sec)
結果:
mysql> show session status like '%sort%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Sort_merge_passes | 0 | | Sort_range | 0 | | Sort_rows | 0 | | Sort_scan | 0 | +-------------------+-------+ 4 rows in set (0.00 sec) mysql> select name, founded from artist where name like 'AUSTRALIA%' order by name \G ...... 22 rows in set (0.00 sec) mysql> show session status like '%sort%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Sort_merge_passes | 0 | | Sort_range | 0 | | Sort_rows | 0 | | Sort_scan | 0 | +-------------------+-------+ 4 rows in set (0.00 sec)