自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊 Order By 是怎么實現(xiàn)的?

數(shù)據(jù)庫 Oracle
實際上,row_id 是 MySQL 的一種優(yōu)化算法,它首先考慮使用全字段排序。只有在認為字段長度過長可能影響效率時,才會采用 row_id 排序方式。此外,如果能夠利用 sort_buffer 完成排序,MySQL 就不會使用臨時文件。

首先排序功能由 ORDER BY 實現(xiàn),具體排列順序取決于優(yōu)化器的選擇。若優(yōu)化器認為索引排序更有效率,則使用索引排序;反之,則使用 filesort(執(zhí)行計劃中額外信息提示:使用 filesort)。然而,索引排序的適用情況有限,且不確定性較高,通常還是會采用 filesort。

在 filesort 排序中,如果排序的數(shù)據(jù)較少,可在內(nèi)存中的 sort_buffer 上完成;否則,需借助臨時文件進行排序。實際排序過程中,如果字段長度較短,可直接在 sort_buffer 中進行全字段排序并返回結(jié)果集。若字段長度較長,可能出于空間考量,采用基于 row_id 的排序,此時會進行二次回表后返回結(jié)果集。

索引排序

眾所周知,索引具備天然的排序?qū)傩?,因此在使?ORDER BY 時,若能充分利用索引,則效率必然最佳。

MySQL 確實可以基于索引執(zhí)行 ORDER BY 查詢,然而這一過程是否必然使用索引完全由優(yōu)化器決定。

CREATE TABLE `t2` (
  `id` INT(11),
  `a` varchar(64) NOT NULL,
  `b` varchar(64) NOT NULL,
  `c` varchar(64) NOT NULL,
  `d` varchar(64) NOT NULL,
  `f` varchar(64) DEFAULT NULL,
  PRIMARY KEY(id),
  UNIQUE KEY `f` (`f`),
  KEY `idx_abc` (`a`,`b`,`c`)
  KEY `idx_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

假設(shè)存在如上所述的表格,在排序過程中可能會出現(xiàn)以下情況(由于優(yōu)化器的干預(yù),以下結(jié)果并不一定可以 100%復(fù)現(xiàn)。根據(jù)我的實驗,在 MySQL 5.7 環(huán)境中是可以的)。

select * from t2 order by a;

-- 不走索引,使用filesort(后面介紹啥是filesort)


select * from t2 order by a limit 100;

-- 走索引


select a,b from t2 order by a limit 100;

-- 走索引


select a,b,c from t2 order by a;

-- 走索引


select a,b,c,d from t2 order by a;

-- 不走索引,使用filesort


select a,b,c,d from t2 where a = "Paidaxing" order by b;

-- 走索引


select a,b,c,d from t2 where b = "Paidaxing" order by a;

-- 不走索引,使用filesort

在使用索引字段進行排序時,優(yōu)化器會根據(jù)成本評估來選擇是否通過索引進行排序。經(jīng)過我的多次驗證,以下情況中,索引排序的概率較高:

  • 查詢的字段和 ORDER BY 的字段組成了一個聯(lián)合索引,并且查詢條件符合最左前綴匹配,使得查詢可以使用索引覆蓋。例如:SELECT a, b, c FROM t2 ORDER BY a;
  • 查詢條件中包含了 LIMIT,并且 LIMIT 的數(shù)量不是很大。(在我測試的表中,數(shù)據(jù)量為 80 萬,當 LIMIT 超過 2 萬多時就不再使用索引排序),例如:ORDER BY a LIMIT 100
  • 雖然未遵循最左前綴匹配,但是前導(dǎo)列通過常量進行了查詢,例如:WHERE a = "Paidaxing" ORDER BY b

filesort 排序

如果無法使用或優(yōu)化器認為索引排序效率不高,MySQL 將執(zhí)行 filesort 操作,以讀取表中的行并對它們進行排序。

在排序過程中,MySQL 為每個線程分配一塊內(nèi)存用于排序,稱為sort_buffer,其大小由 sort_buffer_size控制。

根據(jù) sort_buffer_size 的大小不同,排序操作會發(fā)生在不同的位置:

  • 如果排序數(shù)據(jù)量小于 sort_buffer_size,則排序在內(nèi)存中完成。
  • 如果排序數(shù)據(jù)量大于 sort_buffer_size,則需要利用磁盤臨時文件輔助排序。

臨時文件排序采用歸并排序算法,首先將需要排序的數(shù)據(jù)分配到多個臨時文件中,同時進行排序操作,然后將多個排序完成的文件合并成一個結(jié)果集返回給客戶端。相對于在內(nèi)存中的 sort_buffer 排序,磁盤上的臨時文件排序速度較慢。

除了sort_buffer_size參數(shù)之外,影響排序算法的另一個關(guān)鍵參數(shù)是 max_length_for_sort_data。

max_length_for_sort_data 是 MySQL 中控制用于排序的行數(shù)據(jù)的長度的一個參數(shù),默認值為 1024 字節(jié)。如果單行長度超過該值,MySQL 就會認為單行太大,因此會采用 rowid 排序;否則,會進行全字段排序。

全字段排序

所謂全字段排序,即將要查詢的所有字段都放入 sort_buffer 中,然后根據(jù)排序字段進行排序,排序完成后直接將結(jié)果集返回給客戶端。

假設(shè)我們有以下查詢 SQL:

select a,d,f from t2 where a = "Paidaxing" order by d;

--

因為此處涉及的字段為 a、d、f 三個,因此將滿足 WHERE 條件的所有數(shù)據(jù)的 a、d、f 字段都放入 sort_buffer 中,然后根據(jù) d 字段在 sort_buffer 中進行排序,排序完成后返回給客戶端的大致過程如下:

  1. 從索引 a 中取出滿足條件 a = "Paidaxing" 的第一條記錄的主鍵 ID。
  2. 根據(jù)主鍵 ID 回表,提取 a、d、f 三個字段的值,并將它們存入 sort_buffer。
  3. 繼續(xù)查詢下一個符合 a = "Paidaxing" 條件的記錄,重復(fù)執(zhí)行第 1 和第 2 步驟。
  4. 在 sort_buffer 中根據(jù) d 字段進行排序。
  5. 將排序后的結(jié)果集返回給客戶端。

圖片圖片

以上過程中,如果數(shù)據(jù)在 sort_buffer 中無法全部存放,則會使用臨時文件,并對臨時文件進行歸并排序。

全字段排序的優(yōu)點在于只需要對原表進行一次回表查詢(每條記錄只需回表一次),排序完成后可以直接返回所需字段,因此效率較高。但其缺點在于,如果要查詢的字段較多,會占用大量 sort_buffer 空間,導(dǎo)致可存儲的數(shù)據(jù)量減少。當需要排序的數(shù)據(jù)量增大時,可能會使用臨時文件,從而導(dǎo)致整體性能下降。

為避免這個問題,可以采用 row_id 排序的方式。

row_id 排序

這個也很好理解,即在構(gòu)建 sort_buffer 時,不需要將所有要查詢的字段都放進去,只需要將排序字段和主鍵放入即可。

select a,d,f from t2 where a = "Paidaxing" order by d;

比如這個 SQL,只需要將 d 和 id 放入 sort_buffer 中,首先按照 d 進行排序。排序完成后,根據(jù) id 將對應(yīng)的 a、d、f 幾個字段查詢出來,然后返回給客戶端的大致過程如下:

  1. 從索引 a 中取出符合條件 a = "Paidaxing" 的第一條記錄的主鍵 ID。
  2. 根據(jù)主鍵 ID 回表,提取 d 字段的值,并將其存入 sort_buffer。
  3. 繼續(xù)查詢下一個符合條件 a = "Paidaxing" 的記錄,重復(fù)執(zhí)行第 1 和第 2 步驟。
  4. 在 sort_buffer 中根據(jù) d 進行排序。
  5. 根據(jù)排序后的 id,回表查詢出對應(yīng)的 a、d、f 幾個字段。
  6. 將結(jié)果集返回給客戶端。

圖片圖片

以上的第五步,與全字段排序算法相比確實多了一次回表操作。因此,這種方案的效率肯定會稍慢一些。

如何選擇

如何選擇排序方式?

實際上,row_id 是 MySQL 的一種優(yōu)化算法,它首先考慮使用全字段排序。只有在認為字段長度過長可能影響效率時,才會采用 row_id 排序方式。此外,如果能夠利用 sort_buffer 完成排序,MySQL 就不會使用臨時文件。

綜上所述,MySQL 在選擇排序方式時會優(yōu)先考慮速度、內(nèi)存和減少回表次數(shù)等因素。

責任編輯:武曉燕 來源: 碼上遇見你
相關(guān)推薦

2021-09-22 05:55:18

Eslint disble算法

2021-07-02 07:06:20

調(diào)試代碼crash

2022-06-09 09:20:41

ahooksaxios

2022-09-30 00:03:03

JS斷點線程

2022-10-08 00:07:00

JSV8調(diào)用棧

2024-12-23 15:05:29

2021-08-23 08:27:43

innodb數(shù)據(jù)庫存儲引擎

2022-02-11 09:31:23

IPV4IP地址IANA

2022-02-18 08:26:12

TopK數(shù)組面試題

2021-07-14 14:05:24

Fragment項目結(jié)構(gòu)

2009-02-17 18:52:06

網(wǎng)絡(luò)虛擬化路由系統(tǒng)數(shù)據(jù)中心

2024-09-18 13:49:42

2021-08-30 22:38:47

VscodeMarkdown預(yù)覽

2022-05-30 16:19:26

C#多態(tài)底層虛方法

2021-07-20 08:03:43

微服務(wù)應(yīng)用程序

2020-06-17 07:40:26

監(jiān)控系統(tǒng)zabbix

2021-07-26 05:10:13

JavaJakarta EEJSR

2021-02-05 08:42:21

云原生系統(tǒng)方式

2022-03-18 10:43:12

WebSocketHTML5TCP 連接

2009-03-26 13:43:59

實現(xiàn)Order ByMySQL
點贊
收藏

51CTO技術(shù)棧公眾號