MySQL中利用索引對(duì)數(shù)據(jù)進(jìn)行排序的基礎(chǔ)教程
MySQL中,有兩種方式生成有序結(jié)果集:一是使用filesort,二是按索引順序掃描。利用索引進(jìn)行排序操作是非??斓?,而且可以利用同一索引同時(shí)進(jìn)行查找和排序操作。當(dāng)索引的順序與ORDER BY中的列順序相同且所有的列是同一方向(全部升序或者全部降序)時(shí),可以使用索引來排序。如果查詢是連接多個(gè)表,僅當(dāng)ORDER BY中的所有列都是第一個(gè)表的列時(shí)才會(huì)使用索引。其它情況都會(huì)使用filesort。
MySQL索引通常是被用于提高WHERE條件的數(shù)據(jù)行匹配或者執(zhí)行聯(lián)結(jié)操作時(shí)匹配其它表的數(shù)據(jù)行的搜索速度。
MySQL也能利用索引來快速地執(zhí)行ORDER BY和GROUP BY語句的排序和分組操作。
通過索引優(yōu)化來實(shí)現(xiàn)MySQL的ORDER BY語句優(yōu)化:
create table actor( actor_id int unsigned NOT NULL AUTO_INCREMENT, name varchar(16) NOT NULL DEFAULT '', password varchar(16) NOT NULL DEFAULT '', PRIMARY KEY(actor_id), KEY (name) ) ENGINE=InnoDB insert into actor(name,password) values('cat01','1234567'); insert into actor(name,password) values('cat02','1234567'); insert into actor(name,password) values('ddddd','1234567'); insert into actor(name,password) values('aaaaa','1234567');
mysql> explain select actor_id from actor order by actor_id \G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: actor type: index possible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 4 Extra: Using index 1 row in set (0.00 sec)
mysql> explain select actor_id from actor order by password \G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: actor type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4 Extra: Using filesort 1 row in set (0.00 sec)
mysql> explain select actor_id from actor order by name \G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: actor type: index possible_keys: NULL key: name key_len: 18 ref: NULL rows: 4 Extra: Using index 1 row in set (0.00 sec)
下面來羅列一些常見的索引對(duì)ORFER BY的優(yōu)化情況:
1、如果一個(gè)SQL語句形如:
SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort];
在[sort]這個(gè)欄位上建立索引就可以實(shí)現(xiàn)利用索引進(jìn)行order by 優(yōu)化。
2、WHERE + ORDER BY的索引優(yōu)化,形如:
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [value] ORDER BY [sort];
建立一個(gè)聯(lián)合索引(columnX,sort)來實(shí)現(xiàn)order by 優(yōu)化。
注意:如果columnX對(duì)應(yīng)多個(gè)值,如下面語句就無法利用索引來實(shí)現(xiàn)order by的優(yōu)化
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY[sort];
3、WHERE+ 多個(gè)字段ORDER BY
SELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;
建立索引(uid,x,y)實(shí)現(xiàn)order by的優(yōu)化,比建立(x,y,uid)索引效果要好得多。
MySQL Order By不能使用索引來優(yōu)化排序的情況
* 對(duì)不同的索引鍵做 ORDER BY :(key1,key2分別建立索引)
SELECT * FROM t1 ORDER BY key1, key2;
* 在非連續(xù)的索引鍵部分上做 ORDER BY:(key_part1,key_part2建立聯(lián)合索引;key2建立索引)
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
* 同時(shí)使用了 ASC 和 DESC:(key_part1,key_part2建立聯(lián)合索引)
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
* 用于搜索記錄的索引鍵和做 ORDER BY 的不是同一個(gè):(key1,key2分別建立索引)
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
* 如果在WHERE和ORDER BY的欄位上應(yīng)用表達(dá)式(函數(shù))時(shí),則無法利用索引來實(shí)現(xiàn)order by的優(yōu)化
SELECT * FROM t1 ORDER BY YEAR(logindate) LIMIT 0,10;
當(dāng)MySQL不能使用索引進(jìn)行排序時(shí),就會(huì)利用自己的排序算法(快速排序算法)在內(nèi)存(sort buffer)中對(duì)數(shù)據(jù)進(jìn)行排序,如果內(nèi)存裝載不下,它會(huì)將磁盤上的數(shù)據(jù)進(jìn)行分塊,再對(duì)各個(gè)數(shù)據(jù)塊進(jìn)行排序,然后將各個(gè)塊合并成有序的結(jié)果集(實(shí)際上就是外排序)。對(duì)于filesort,MySQL有兩種排序算法。
1.兩遍掃描算法(Two passes)
實(shí)現(xiàn)方式是先將須要排序的字段和可以直接定位到相關(guān)行數(shù)據(jù)的指針信息取出,然后在設(shè)定的內(nèi)存(通過參數(shù)sort_buffer_size設(shè)定)中進(jìn)行排序,完成排序之后再次通過行指針信息取出所需的Columns。
注:該算法是4.1之前采用的算法,它需要兩次訪問數(shù)據(jù),尤其是第二次讀取操作會(huì)導(dǎo)致大量的隨機(jī)I/O操作。另一方面,內(nèi)存開銷較小。
2. 一次掃描算法(single pass)
該算法一次性將所需的Columns全部取出,在內(nèi)存中排序后直接將結(jié)果輸出。
注:從 MySQL 4.1 版本開始使用該算法。它減少了I/O的次數(shù),效率較高,但是內(nèi)存開銷也較大。如果我們將并不需要的Columns也取出來,就會(huì)極大地浪費(fèi)排序過程所需要的內(nèi)存。在 MySQL 4.1 之后的版本中,可以通過設(shè)置 max_length_for_sort_data 參數(shù)來控制 MySQL 選擇第一種排序算法還是第二種。當(dāng)取出的所有大字段總大小大于 max_length_for_sort_data 的設(shè)置時(shí),MySQL 就會(huì)選擇使用第一種排序算法,反之,則會(huì)選擇第二種。為了盡可能地提高排序性能,我們自然更希望使用第二種排序算法,所以在 Query 中僅僅取出需要的 Columns 是非常有必要的。
當(dāng)對(duì)連接操作進(jìn)行排序時(shí),如果ORDER BY僅僅引用第一個(gè)表的列,MySQL對(duì)該表進(jìn)行filesort操作,然后進(jìn)行連接處理,此時(shí),EXPLAIN輸出“Using filesort”;否則,MySQL必須將查詢的結(jié)果集生成一個(gè)臨時(shí)表,在連接完成之后進(jìn)行filesort操作,此時(shí),EXPLAIN輸出“Using temporary;Using filesort”。
- 數(shù)據(jù)庫(kù)查詢排序使用隨機(jī)排序結(jié)果示例(Oracle/MySQL/MS SQL Server)
- mysql查詢語句通過limit來限制查詢的行數(shù)
- mysql的中文數(shù)據(jù)按拼音排序的2個(gè)方法
- MYSQL必知必會(huì)讀書筆記第五章之排序檢索數(shù)據(jù)
- Yii2實(shí)現(xiàn)跨mysql數(shù)據(jù)庫(kù)關(guān)聯(lián)查詢排序功能代碼
- MySQL asc、desc數(shù)據(jù)排序的實(shí)現(xiàn)
- MySQL數(shù)據(jù)庫(kù)索引order?by排序精講
- MySQL限制查詢和數(shù)據(jù)排序介紹
相關(guān)文章
簡(jiǎn)析mysql字符集導(dǎo)致恢復(fù)數(shù)據(jù)庫(kù)報(bào)錯(cuò)問題
這篇文章主要介紹了簡(jiǎn)析mysql字符集導(dǎo)致恢復(fù)數(shù)據(jù)庫(kù)報(bào)錯(cuò)問題,具有一定參考價(jià)值,需要的朋友可以了解。2017-10-10MySql連接數(shù)據(jù)庫(kù)常用參數(shù)及代碼解讀
這篇文章主要介紹了MySql連接數(shù)據(jù)庫(kù)常用參數(shù)及代碼解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Mysql中校對(duì)集utf8_unicode_ci與utf8_general_ci的區(qū)別說明
一直對(duì)utf8_unicode_ci與utf8_general_ci這2個(gè)校對(duì)集很迷惑,今天查了手冊(cè)有了點(diǎn)眉目。不過對(duì)中文字符集來說采用utf8_unicode_ci與utf8_general_ci時(shí)有何區(qū)別還是不清楚2012-03-03Mysql出生日期轉(zhuǎn)換為年齡并分組統(tǒng)計(jì)人數(shù)的方法示例
這篇文章主要給大家介紹了關(guān)于Mysql出生日期轉(zhuǎn)換為年齡并分組統(tǒng)計(jì)人數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11MySQL對(duì)相同字段創(chuàng)建不同索引解析
這篇文章主要為大家介紹了MySQL?對(duì)相同字段創(chuàng)建不同索引解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11MySql超長(zhǎng)自動(dòng)截?cái)鄬?shí)例詳解
這篇文章主要介紹了MySql超長(zhǎng)自動(dòng)截?cái)鄬?shí)例詳解的相關(guān)資料,這里通過實(shí)例來說明如何實(shí)現(xiàn)自動(dòng)截?cái)嗟墓δ埽枰呐笥芽梢詤⒖枷?/div> 2017-07-07最新評(píng)論