天天看點

(六)MySQL如何優化--ORDER BY

---

title: 不懂SQL優化?那你就OUT了(六)

MySQL如何優化--ORDER BY

date: 2018-12-08

categories: 資料庫優化

---

(六)MySQL如何優化--ORDER BY

在日常開發中,我們經常會使用 order by 子句對某些資料進行排序處理,那麼在mysql中使用order by子句時,我們應該怎樣優化order by 子句後的查詢字段來提高查詢效率和排序速度。

在mysql中使用 order by 進行排序有兩種方式:

1. 掃描有序索引進行排序(推薦)

2. 使用檔案進行排序(using filesort:記憶體/磁盤檔案排序擷取結果 )

在InnoDB存儲引擎以B+樹作為索引的底層實作,B+樹的葉子節點存儲着所有資料頁而内部節點不存放資料資訊,并且所有葉子節點形成一個(雙向)連結清單。

你可以簡單的了解為:索引是一種特殊的檔案,當我們建立索引時,mysql會使用雙向連結清單的方式來事先給資料進行排序。

例如:

CREATE TABLE t_testOrderBy(

userid INT PRIMARY KEY AUTO_INCREMENT, -- 使用者編号

username VARCHAR(25), -- 使用者姓名

userAge INT, -- 使用者年齡

usergender CHAR(3), -- 使用者性别

provice VARCHAR(25), -- 所在省份

city VARCHAR(25), -- 所在城市

address VARCHAR(200) -- 詳細位址

);

測試資料:

INSERT INTO t_testOrderBy VALUES(NULL,'張三',18,'男','四川省','成都市','xxxx路222号');

INSERT INTO t_testOrderBy VALUES(NULL,'李四',20,'女','雲南省','昆明市','xxx北路12号');

INSERT INTO t_testOrderBy VALUES(NULL,'王五',24,'男','貴州省','遵義市','xxxxx路18号');

INSERT INTO t_testOrderBy VALUES(NULL,'趙六',19,'女','四川省','綿陽市','xx路234号');

INSERT INTO t_testOrderBy VALUES(NULL,'孫琦',28,'男','雲南省','玉溪市','xxxx路324号');

INSERT INTO t_testOrderBy VALUES(NULL,'王曉琪',21,'女','雲南省','玉溪市','xxxx路123号');

例如:

圖1:

(六)MySQL如何優化--ORDER BY

從圖1可以看出:

使用userid進行排序時,userid上有主鍵索引,mysql會直接周遊userid索引的葉子節點連結清單,不需要進行額外的排序操作,這就是用索引掃描來排序。

使用 username 字段上沒有任何索引,此時B+樹結構不存在,mysql就隻能先掃表篩選出符合條件的資料,再将篩選結果根據username排序。這個排序過程就是filesort。

### 使用有序索引排序時

sql語句中,where子句和order by 子句都可以使用索引, where子句使用索引避免全表掃描,order by 子句使用索引盡量避開使用檔案排序(filesort),以提高查詢效率。

雖然索引能提高查詢效率,但在一條sql裡,對于一張表的查詢 一次隻能使用一個索引(注:排除發生index merge的可能性),也就是說當where子句與order by 子句使用的索引不一緻時,MySQL隻能使用其中一個索引(B+樹)。

####order by 可以使用索引

1. 當select的字段包含在索引中時,能利用到索引排序功能,進行覆寫索引掃描.

例如: 為表中的username添加索引。

(六)MySQL如何優化--ORDER BY
(六)MySQL如何優化--ORDER BY
(六)MySQL如何優化--ORDER BY

可以看出當 select 字段中包含了 userage(未建立索引)時,則不能使用索引。

2.當有聯合索引時,order by 子句使用索引必須遵循索引的最左字首原則。

例如: 為 省份,城市,詳細位址建立聯合索引

(六)MySQL如何優化--ORDER BY
(六)MySQL如何優化--ORDER BY

當不遵循最左字首原則時,則會使用filesort

(六)MySQL如何優化--ORDER BY

3.聯合索引中的一部分做等值查詢 ,另一部分作為排序字段。(當然還是要遵循最左字首原則)

(六)MySQL如何優化--ORDER BY

####order by 不使用索引排序

1.select字段在多個索引中,無法使用索引排序。

(六)MySQL如何優化--ORDER BY

從上圖中可以看出,username的一個獨立的是以,二而provice是聯合索引,當select字段中有多個索引列時,無法使用索引排序

2.對不同的關鍵字使用ORDER BY:

(六)MySQL如何優化--ORDER BY

3.當有聯合索引時,order by 子句使用索引 不 遵循索引的最左字首原則,無法使用索引排序

(六)MySQL如何優化--ORDER BY

4. 升降序不一緻,無法使用索引排序。

(六)MySQL如何優化--ORDER BY

5.order by 的字段使用函數

6.傳回資料量過大也會不使用索引。

## 使用檔案進行排序(後面在介紹)

對于不能利用索引避免排序的sql,資料庫不得不自己實作排序功能以滿足使用者需求,此時sql的執行計劃中會出現“Using filesort”,這裡需要注意的是filesort并不意味着就是檔案排序,其實也有可能是記憶體排序,這個主要由sort_buffer_size參數與結果集大小确定。

如果排序不可避免,可以用下面的辦法加速:

1. 避免使用 “select * ” 。

2. 增加sort_buffer_size變量的大小。

3. 增加read_rnd_buffer_size變量的大小。

4. 更改tmpdir指向具有大量空閑空間的專用檔案系統。

5. 使用合适的列大小存儲具體的内容,比如對于city字段 varchar(25)比varchar(200)能擷取更好的性能.

##order by 總結

(六)MySQL如何優化--ORDER BY

轉載于:https://www.cnblogs.com/ysviewvicn/p/10288302.html