亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

淺談MySQL排序原理與案例分析

2024-07-24 13:08:56
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了淺談MySQL排序原理與案例分析的相關資料,需要的朋友可以參考下
 

前言

排序是數據庫中的一個基本功能,MySQL也不例外。用戶通過Order by語句即能達到將指定的結果集排序的目的,其實不僅僅是Order by語句,Group by語句,Distinct語句都會隱含使用排序。本文首先會簡單介紹SQL如何利用索引避免排序代價,然后會介紹MySQL實現排序的內部原理,并介紹與排序相關的參數,最后會給出幾個“奇怪”排序例子,來談談排序一致性問題,并說明產生現象的本質原因。

1.排序優化與索引使用

為了優化SQL語句的排序性能,最好的情況是避免排序,合理利用索引是一個不錯的方法。因為索引本身也是有序的,如果在需要排序的字段上面建立了合適的索引,那么就可以跳過排序的過程,提高SQL的查詢速度。下面我通過一些典型的SQL來說明哪些SQL可以利用索引減少排序,哪些SQL不能。假設t1表存在索引key1(key_part1,key_part2),key2(key2)

a.可以利用索引避免排序的SQL

SELECT * FROM t1 ORDER BY key_part1,key_part2;SELECT * FROM t1 WHERE key_part1 = constant ORDER BY key_part2;SELECT * FROM t1 WHERE key_part1 > constant ORDER BY key_part1 ASC;SELECT * FROM t1 WHERE key_part1 = constant1 AND key_part2 > constant2 ORDER BY key_part2;

 

b.不能利用索引避免排序的SQL

//排序字段在多個索引中,無法使用索引排序SELECT * FROM t1 ORDER BY key_part1,key_part2, key2; //排序鍵順序與索引中列順序不一致,無法使用索引排序SELECT * FROM t1 ORDER BY key_part2, key_part1; //升降序不一致,無法使用索引排序SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC; //key_part1是范圍查詢,key_part2無法使用索引排序SELECT * FROM t1 WHERE key_part1> constant ORDER BY key_part2;

 

2.排序實現的算法

對于不能利用索引避免排序的SQL,數據庫不得不自己實現排序功能以滿足用戶需求,此時SQL的執行計劃中會出現“Using filesort”,這里需要注意的是filesort并不意味著就是文件排序,其實也有可能是內存排序,這個主要由sort_buffer_size參數與結果集大小確定。MySQL內部實現排序主要有3種方式,常規排序,優化排序和優先隊列排序,主要涉及3種排序算法:快速排序、歸并排序和堆排序。假設表結構和SQL語句如下:

CREATE TABLE t1(id int, col1 varchar(64), col2 varchar(64), col3 varchar(64), PRIMARY KEY(id),key(col1,col2));SELECT col1,col2,col3 FROM t1 WHERE col1>100 ORDER BY col2;

a.常規排序
(1).從表t1中獲取滿足WHERE條件的記錄
(2).對于每條記錄,將記錄的主鍵+排序鍵(id,col2)取出放入sort buffer
(3).如果sort buffer可以存放所有滿足條件的(id,col2)對,則進行排序;否則sort buffer滿后,進行排序并固化到臨時文件中。(排序算法采用的是快速排序算法)
(4).若排序中產生了臨時文件,需要利用歸并排序算法,保證臨時文件中記錄是有序的
(5).循環執行上述過程,直到所有滿足條件的記錄全部參與排序
(6).掃描排好序的(id,col2)對,并利用id去撈取SELECT需要返回的列(col1,col2,col3)
(7).將獲取的結果集返回給用戶。
從上述流程來看,是否使用文件排序主要看sort buffer是否能容下需要排序的(id,col2)對,這個buffer的大小由sort_buffer_size參數控制。此外一次排序需要兩次IO,一次是撈(id,col2),第二次是撈(col1,col2,col3),由于返回的結果集是按col2排序,因此id是亂序的,通過亂序的id去撈(col1,col2,col3)時會產生大量的隨機IO。對于第二次MySQL本身一個優化,即在撈之前首先將id排序,并放入緩沖區,這個緩存區大小由參數read_rnd_buffer_size控制,然后有序去撈記錄,將隨機IO轉為順序IO。
b.優化排序
常規排序方式除了排序本身,還需要額外兩次IO。優化的排序方式相對于常規排序,減少了第二次IO。主要區別在于,放入sort buffer不是(id,col2),而是(col1,col2,col3)。由于sort buffer中包含了查詢需要的所有字段,因此排序完成后可以直接返回,無需二次撈數據。這種方式的代價在于,同樣大小的sort buffer,能存放的(col1,col2,col3)數目要小于(id,col2),如果sort buffer不夠大,可能導致需要寫臨時文件,造成額外的IO。當然MySQL提供了參數max_length_for_sort_data,只有當排序元組小于max_length_for_sort_data時,才能利用優化排序方式,否則只能用常規排序方式。
c.優先隊列排序
為了得到最終的排序結果,無論怎樣,我們都需要將所有滿足條件的記錄進行排序才能返回。那么相對于優化排序方式,是否還有優化空間呢?5.6版本針對Order by limit M,N語句,在空間層面做了優化,加入了一種新的排序方式--優先隊列,這種方式采用堆排序實現。堆排序算法特征正好可以解limit M,N 這類排序的問題,雖然仍然需要所有元素參與排序,但是只需要M+N個元組的sort buffer空間即可,對于M,N很小的場景,基本不會因為sort buffer不夠而導致需要臨時文件進行歸并排序的問題。對于升序,采用大頂堆,最終堆中的元素組成了最小的N個元素,對于降序,采用小頂堆,最終堆中的元素組成了最大的N的元素。

3.排序不一致問題

案例1

Mysql從5.5遷移到5.6以后,發現分頁出現了重復值。
測試表與數據:

create table t1(id int primary key, c1 int, c2 varchar(128));insert into t1 values(1,1,'a');insert into t1 values(2,2,'b');insert into t1 values(3,2,'c');insert into t1 values(4,2,'d');insert into t1 values(5,3,'e');insert into t1 values(6,4,'f');insert into t1 values(7,5,'g');

假設每頁3條記錄,第一頁limit 0,3和第二頁limit 3,3查詢結果如下:

MySQL,排序原理

我們可以看到 id為4的這條記錄居然同時出現在兩次查詢中,這明顯是不符合預期的,而且在5.5版本中沒有這個問題。產生這個現象的原因就是5.6針對limit M,N的語句采用了優先隊列,而優先隊列采用堆實現,比如上述的例子order by c1 asc limit 0,3 需要采用大小為3的大頂堆;limit 3,3需要采用大小為6的大頂堆。由于c1為2的記錄有3條,而堆排序是非穩定的(對于相同的key值,無法保證排序后與排序前的位置一致),所以導致分頁重復的現象。為了避免這個問題,我們可以在排序中加上唯一值,比如主鍵id,這樣由于id是唯一的,確保參與排序的key值不相同。將SQL寫成如下:

select * from t1 order by c1,id asc limit 0,3;select * from t1 order by c1,id asc limit 3,3;

案例2

兩個類似的查詢語句,除了返回列不同,其它都相同,但排序的結果不一致。
測試表與數據:

create table t2(id int primary key, status int, c1 varchar(255),c2 varchar(255),c3 varchar(255),key(c1));insert into t2 values(7,1,'a',repeat('a',255),repeat('a',255));insert into t2 values(6,2,'b',repeat('a',255),repeat('a',255));insert into t2 values(5,2,'c',repeat('a',255),repeat('a',255));insert into t2 values(4,2,'a',repeat('a',255),repeat('a',255));insert into t2 values(3,3,'b',repeat('a',255),repeat('a',255));insert into t2 values(2,4,'c',repeat('a',255),repeat('a',255));insert into t2 values(1,5,'a',repeat('a',255),repeat('a',255));

分別執行SQL語句:

select id,status,c1,c2 from t2 force index(c1) where c1>='b' order by status;select id,status from t2 force index(c1) where c1>='b' order by status;

執行結果如下:

MySQL,排序原理

看看兩者的執行計劃是否相同

MySQL,排序原理

為了說明問題,我在語句中加了force index的hint,確保能走上c1列索引。語句通過c1列索引撈取id,然后去表中撈取返回的列。根據c1列值的大小,記錄在c1索引中的相對位置如下:

(c1,id)===(b,6),(b,3),(5,c),(c,2),對應的status值分別為2 3 2 4。從表中撈取數據并按status排序,則相對位置變為(6,2,b),(5,2,c),(3,3,c),(2,4,c),這就是第二條語句查詢返回的結果,那么為什么第一條查詢語句(6,2,b),(5,2,c)是調換順序的呢?這里要看我之前提到的a.常規排序和b.優化排序中標紅的部分,就可以明白原因了。由于第一條查詢返回的列的字節數超過了max_length_for_sort_data,導致排序采用的是常規排序,而在這種情況下MYSQL將rowid排序,將隨機IO轉為順序IO,所以返回的是5在前,6在后;而第二條查詢采用的是優化排序,沒有第二次撈取數據的過程,保持了排序后記錄的相對位置。對于第一條語句,若想采用優化排序,我們將max_length_for_sort_data設置調大即可,比如2048。

MySQL,排序原理

下面是本人關于mysql 自定義排序(field,INSTR,locate)的一點心得,希望對大家有所幫助
首先說明這里有三個函數(order by field,ORDER BY INSTR,ORDER BY locate)

原表:

 id user pass aaa aaa bbb bbb ccc ccc ddd ddd eee eee fff fff 

下面是我執行后的結果:

SELECT * FROM `user` order by field(2,3,5,4,id) asc
id user pass aaa aaa ccc ccc ddd ddd eee eee fff fff bbb bbb 

根據結果分析:order by field(2,3,5,4,1,6) 結果顯示順序為:1 3 4 5 6 2

SELECT * FROM `user` order by field(2,3,5,4,id) desc
id user pass bbb bbb aaa aaa ccc ccc ddd ddd eee eee fff fff 

根據結果分析:order by field(2,3,5,4,1,6) 結果顯示順序為:2 1 3 4 5 6

SELECT * FROM `user` ORDER BY INSTR( '2,3,5,4', id ) ASC 
id user pass aaa aaa fff fff bbb bbb ccc ccc eee eee ddd ddd 

根據結果分析:order by INSTR(2,3,5,4,1,6) 結果顯示順序為:1 6 2 3 5 4

SELECT * FROM `user` ORDER BY INSTR( '2,3,5,4', id ) DESC
id user pass ddd ddd eee eee ccc ccc bbb bbb aaa aaa fff fff 

根據結果分析:order by INSTR(2,3,5,4,1,6) 結果顯示順序為:4 5 3 2 1 6

SELECT * FROM `user` ORDER BY locate( id, '2,3,5,4' ) ASC 

  id  user  pass  

aaa aaa fff fff bbb bbb ccc ccc eee eee ddd ddd

根據結果分析:order by locate(2,3,5,4,1,6) 結果顯示順序為:1 6 2 3 5 4

SELECT * FROM `user` ORDER BY locate( id, '2,3,5,4' ) DESC 
 id user pass ddd ddd eee eee ccc ccc bbb bbb aaa aaa fff fff 

根據結果分析:order by locate(2,3,5,4,1,6) 結果顯示順序為:4 5 3 2 1 6
如我想要查找的數據庫中的ID順序首先是(2,3,5,4)然后在是其它的ID順序,你首先要把他降序排即(4 5 3 2),然后在 SELECT * FROM `user` ORDER BY INSTR( '4,5,3,2', id ) DESC limit 0,10 或用 SELECT *  FROM `user` ORDER BY locate( id, '4,5,3,2' ) DESC 就得到你想要的結果了。

 id user pass bbb bbb ccc ccc eee eee ddd ddd aaa aaa fff fff


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品日韩激情在线电影| 亚洲人线精品午夜| 欧美中文字幕视频在线观看| 国产在线视频91| 精品视频偷偷看在线观看| 久久久久久免费精品| 久久久精品免费| 国产日韩欧美另类| 欧美激情在线观看| 91免费看视频.| 国产一区二区丝袜高跟鞋图片| 亚洲欧美国产精品va在线观看| 欧美人与性动交| 欧美丝袜美女中出在线| 国产欧洲精品视频| 亚洲区在线播放| 91高潮精品免费porn| 不卡中文字幕av| 日韩av黄色在线观看| 久操成人在线视频| 日韩小视频网址| www.欧美免费| 国产精品久久久久久久久久尿| 91精品国产成人www| 久热精品视频在线| 精品国产鲁一鲁一区二区张丽| 国产suv精品一区二区| 日韩中文字幕在线看| 久久久精品久久久| 亚洲3p在线观看| 国产精品热视频| 欧美精品国产精品日韩精品| 91地址最新发布| 欧美夜福利tv在线| 日韩欧美高清视频| 亚洲综合日韩中文字幕v在线| 日韩欧美中文字幕在线播放| 国产一区二区日韩精品欧美精品| 国产一区二区三区视频免费| 成人免费在线视频网址| 久久97精品久久久久久久不卡| 久久久免费在线观看| 亚洲第一精品自拍| 亚洲福利视频免费观看| 日韩欧美国产免费播放| 亚洲性线免费观看视频成熟| 国产欧美一区二区三区四区| 成人午夜高潮视频| 国产精品国产福利国产秒拍| 91av在线精品| 亚洲精品视频二区| 久久夜色撩人精品| 91高清视频在线免费观看| 国产日韩欧美中文在线播放| 国产精品视频播放| 日韩视频在线免费| 久久综合国产精品台湾中文娱乐网| 国产性猛交xxxx免费看久久| 日韩成人性视频| 日韩黄色高清视频| 日本欧美爱爱爱| 欧美一级淫片丝袜脚交| 色综合老司机第九色激情| 久久久精品视频成人| 69国产精品成人在线播放| 欧美一级免费视频| 最新国产成人av网站网址麻豆| 日本欧美一二三区| 日韩美女在线观看一区| 精品国产鲁一鲁一区二区张丽| 欧美激情视频播放| 精品在线小视频| 亚洲天堂免费在线| 国产精品久久久久久久久免费看| 色综合视频一区中文字幕| 亚洲精品国产精品乱码不99按摩| 91精品国产乱码久久久久久久久| 中文一区二区视频| 国产在线视频91| 91爱视频在线| 一本久久综合亚洲鲁鲁| 91精品国产高清久久久久久| 91在线色戒在线| 日韩中文字幕在线免费观看| 亚洲欧洲午夜一线一品| 亚洲网址你懂得| 色老头一区二区三区在线观看| 91免费精品国偷自产在线| 色中色综合影院手机版在线观看| 国产精品日韩欧美| 亚洲国产成人一区| 亚洲一二三在线| 97国产成人精品视频| 国内精品久久久久久中文字幕| 2019国产精品自在线拍国产不卡| 亚洲欧洲日韩国产| 国产成人精品在线观看| 亚洲a一级视频| 欧美日韩在线影院| 3344国产精品免费看| 亚洲第一精品夜夜躁人人爽| 亚洲xxx视频| 成人精品在线观看| 亚洲欧美在线一区二区| 成人有码视频在线播放| 亚洲专区国产精品| 成人免费观看a| 国产精品视频1区| www国产亚洲精品久久网站| 中文字幕日韩欧美在线| 91精品久久久久久久久| 亚洲精品99久久久久| 成人精品一区二区三区电影免费| 午夜精品久久久久久久99热浪潮| 欧美日韩性视频| 成人网中文字幕| 亚洲激情小视频| 国产又爽又黄的激情精品视频| 欧美午夜视频在线观看| 欧美日韩裸体免费视频| 亚洲精品91美女久久久久久久| 久久久久久免费精品| 91亚洲va在线va天堂va国| 美女999久久久精品视频| 97视频在线观看亚洲| 日韩国产精品亚洲а∨天堂免| 亚洲免费伊人电影在线观看av| 欧美成年人视频网站欧美| 2020久久国产精品| 久久久国产一区二区三区| 日韩国产欧美区| 久久av在线看| 成人精品久久久| 亚洲美女免费精品视频在线观看| 中文精品99久久国产香蕉| 国产精品人人做人人爽| 成人啪啪免费看| 国产精品电影在线观看| 成人精品久久久| 久久久久www| 国产精品亚洲美女av网站| 97精品在线观看| 国内精品视频久久| 精品国产一区二区三区久久狼黑人| 精品国产区一区二区三区在线观看| 欧美高清视频在线| 亚洲成人国产精品| 日韩精品999| 97国产精品久久| 国产免费观看久久黄| 国产成人拍精品视频午夜网站| 亚洲精品视频久久| 日韩av电影手机在线观看| 国产亚洲精品久久久| 欧美日韩国产中文精品字幕自在自线| 日韩女在线观看| 欧美激情视频网| 热久久99这里有精品| 欧美激情在线视频二区| 成人啪啪免费看| 欧美中文在线字幕| 日韩成人中文字幕在线观看| 在线播放日韩专区| 日韩视频―中文字幕|