日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL 优化 —— ORDER BY 优化

發布時間:2025/3/12 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 优化 —— ORDER BY 优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

本文翻譯自MySQL 官網:ORDER BY Optimization,MySQL 版本:5.7。

這一部分描述了MySQL何時會使用索引來滿足order by子句,filesort 操作會在索引不能生效的時候被用到,以及優化器對order by的執行計劃信息。

order by后面有沒有跟著limit,可能會返回不同的記錄順序。

一、使用索引來滿足 ORDER BY

某些情況,MySQL可能會使用索引來滿足order by子句并避免因執行 filesort 操作造成的額外的排序開銷。

即便order by子句并沒有完全與索引匹配,可能也會用到索引,只要索引所有未使用的部分和所有額外的order by 字段在where子句中都是常量。如果索引沒有包含查詢的所有字段,那么只有當索引訪問比其他訪問方法開銷更小的時候才會用到索引。

假設現在有一個索引覆蓋了key_part1, key_part2這兩個字段,下面的查詢可能會用索引來解決order by 的部分。優化器是否真會這么做取決于如果有一個字段必須查詢而它又不在索引中的情況下,讀取索引是否比全表掃描更有效。

  • 在這個查詢中,兩個字段的復合索引可以使優化器避免排序。
SELECT * FROM t1ORDER BY key_part1, key_part2;

但是,查詢使用的是select *,這可能會查詢出比索引列(key_part1 , key_part2)更多的字段。這種情況,掃描整個索引并在表中記錄里查找哪些不是索引列的開銷可能要比掃描整個表然后對結果集排序還要大。如果這樣,優化器通常就不會使用索引。如果select * 只查詢了索引列,那么就會用到索引并避免排序操作。

如果表是一個InnoDB 表,那么表的主鍵默認也是索引的一部分,那么下面的查詢就可以使用索引來解決order by:

SELECT pk, key_part1, key_part2 FROM t1ORDER BY key_part1, key_part2;
  • 在這個查詢中key_part1是常量,所有通過索引訪問到的記錄都會按照key_part2 來排序,并且如果where子句有足夠的選擇性使得索引范圍掃描比全表掃描開銷更小的話,那么覆蓋了(key_part1, key_part2)的復合索引就可以避免排序操作。
SELECT * FROM t1WHERE key_part1 = constantORDER BY key_part2;
  • 下面的兩個查詢,和之前沒有desc的同一查詢,索引的使用情況類似。
SELECT * FROM t1ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1WHERE key_part1 = constantORDER BY key_part2 DESC;
  • 下面的兩個查詢,key_part1 和一個常量進行比較。如果 WHERE 子句有足夠的可選擇性來使索引區間掃描比全表掃描更優,那么索引就會被使用。
SELECT * FROM t1WHERE key_part1 > constantORDER BY key_part1 ASC;SELECT * FROM t1WHERE key_part1 < constantORDER BY key_part1 DESC;
  • 下面的查詢, ORDER BY 沒有使用 key_part1,但是所有被查詢的行都有一個常量的 key_part1 的值,因此依然會使用索引:
SELECT * FROM t1WHERE key_part1 = constant1 AND key_part2 > constant2ORDER BY key_part2;

某些情況,MySQL 不會使用索引來處理 ORDER BY,即便仍然會在 WHERE 子句進行匹配操作時用到索引。例如下面這些:

  • 查詢中的 ORDER BY 使用了不同的 索引:
SELECT * FROM t1 ORDER BY key1, key2;
  • 查詢中的 ORDER BY 使用了不連續的索引部分:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1_part1, key1_part3;
  • 查詢中的 ORDER BY 混用了 ASC 和 DESC:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1_part1, key1_part3;
  • 用于查詢記錄的索引與 ORDER BY 中的索引不是同一個:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
  • 查詢中的 ORDER BY 包含了一個表達式,這個表達式包含索引列名之外的其他項:
SELECT * FROM t1 ORDER BY ABS(key); SELECT * FROM t1 ORDER BY -key;
  • 查詢連接了多張表,并且 ORDER BY 中的字段并不都來自于第一個非常量數據表(博主:如果所有的 ORDER BY 和 GROUP BY子句中的字段都來自同一個表,那么這個表在連接時就作為第一張表。這里的意思是說,如果 ORDER BY 中的字段來自于不同的表,那么就不會用到索引)
  • 查詢中包含不同的 ORDER BY 和 GROUP BY 表達式。
  • ORDER BY 子句中的字段只有字段的前綴有索引。這種情況,索引就不會完全參與排序操作。例如,有一個列聲明為 CHAR(20),但是只有前10個字節建立了索引,那么索引就無法區分(博主:排序最本質的工作就是比較大小,這里的區分就是比較的意思)剩余的10個字節,這時就會使用 filesort 。
  • 索引沒有以一定的順序存儲記錄。例如,memory 存儲引擎中用到的 HASH 索引就是這種不會對記錄進行排序的索引。

另外,用于排序的索引究竟可不可用還會受到字段別名的影響。假設 t1 表的 t1.a 字段建立了索引。下面的語句中,查詢列表中有這個字段 a 。它代表 t1.a ,因為 a 已經建立了索引,所以下面的語句就會用到索引:

SELECT a FROM t1 ORDER BY a;

下面的語句中,查詢列表依然有 a 列,但此 a 非彼 a,這個 a 是一個別名。它代表的是 ABS(a),因為 索引是建立在 a 列上,所以 t1.a 上的索引不會生效:

SELECT ABS(a) AS a FROM t1 ORDER BY a;

下面的語句中, ORDER BY 對 a 進行排序,而在查詢列表中,并沒有叫 a 的列。但是 t1 表中有一個列叫做 a,因此 ORDER BY 指向的是?t1.a ,t1.a 上的索引就會生效。(當然,排序的結果可能與 ORDER BY?ABS(a) 的排序完全不同)

SELECT ABS(a) AS b FROM t1 ORDER BY a;

?默認地,MySQL 會對 GROUP BY col1, col2, ... 進行排序,就好像你的查詢中依然包含 ORDER BY col1, col2, ... 一樣。如果你顯式地包含一個 ORDER BY? 子句,包含了相同的字段列表,MySQL 會把它優化掉,排序依然會發生,且不會有性能犧牲。

如果一個查詢包含 GROUP BY 但是你想避免對結果排序的開銷。你可以通過指定 ORDER BY NULL 來抑制排序。例如:

INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;

優化器可能依然會用排序來實現分組操作。ORDER BY NULL 抑制了對結果的排序,分組操作之前不會有排序來決定結果。

注意:

GROUP BY 默認隱式排序(即 GROUP BY 的字段沒有 ASC 或 DESC)。然而,依賴隱式 GROUP BY 排序或顯式 GROUP BY (即使用聲明的 ASC 或 DESC 來對 GROUP BY 的字段排序)排序都是不推薦的。要排序,請用 ORDER BY 子句。

二、 使用 filesort 來滿足 ORDER BY

如果索引已經無法滿足 ORDER BY 子句,MySQL 會執行 filesort 操作,它的意思是——讀取表中數據然后排序。filesort 會在查詢執行的時候有額外的排序時間。

為了獲取用于 filesort 操作的內存,優化器會預先分配一個固定大小為?sort_buffer_size 個字節。每一個session 會話可以通過改變這個值來避免過度的內存消耗,或者在必要時分配更多內存。

如果結果集真的大到內存已經無法裝下,那么 filesort 操作會在這種必要的時候使用臨時的磁盤文件。有些類型的查詢尤其適合完成內存內的 filesort 操作。例如,下面的查詢形式,優化器就可以使用 filesort 在內存中,而不是使用臨時文件來高效地處理 ORDER BY 操作:

SELECT ... FROM single_table ... ORDER BY non_index_column [DESC] LIMIT [M,]N;

下面的查詢在 web 應用中非常常見,它們用于讓一個很大的結果集展示很少的一些記錄。例如:

SELECT col1, ... FROM t1 ... ORDER BY name LIMIT 10; SELECT col1, ... FROM t1 ... ORDER BY RAND() LIMIT 15;

三、影響 ORDER BY 優化

對于連 filesort 都無法生效的慢查詢,嘗試把 max_length_for_sort_data 系統變量調低到一個適合觸發 filesort 的值。(一個該值設置地太高的癥狀是系統同時會出現高磁盤活動和低CPU 活動

為了加快 ORDER BY 的速度,檢查一下你是否可以使用索引而不是額外的排序時間(博主:即使用 filesort)。如果無法做到,嘗試下面的優化策略:

  • 調大 sort_buffer_size 變量的值。理想狀態下,這個值應該大到足夠整個結果集可以容納在排序緩沖區(為了避免磁盤寫入和合并次數),但是該值最小也必須要足夠容納15個元組。(合并最多15個臨時磁盤文件,每個文件必須有至少一個元組的內存空間)。
  • 考慮到存儲在排序緩沖區中的列值的大小受到 max_sort_length 系統變量的影響。例如,如果元組存儲長字符串字段的值,并且你調大了 max_sort_length?的值,那么排序緩沖區元組的大小也會變大,并且你可能同時需要增大 sort_buffer_size 的大小。對于作為字符串表達式結果計算的列值(例如那些需要一個字符串參數的函數),filesort 算法無法得知表達式的最大長度,所以就一定會給每個元組分配 max_sort_length 的字節數。如果要監控合并次數(合并臨時文件),可以檢查 Sort_merge_passes 狀態變量。
  • 調大 read_rnd_buffer_size 變量可以在同一時間讀取更多的記錄。
  • 改變 tmpdir 系統變量的值,使其指向一個具有大量空閑空間的專用文件系統。該變量值會列出幾個以循環方式使用的路徑。使用這個功能可以讓負載分散到多個目錄。在Unix 系統上以冒號(:)分隔路徑,在 Windows 系統上以分號(;)分隔路徑。路徑應該命名位于不同物理磁盤上的文件系統中的目錄,而不是同一磁盤上的不同分區。

四、ORDER BY 的執行計劃信息

使用 EXPLAIN ,你可以檢查MySQL 是否有用到索引來解決 ORDER BY 子句:

  • 如果在輸出的執行計劃中 Extra 列不包含 "Using filesort" ,那么索引排序生效,filesort 不會執行。
  • 如果在輸出的執行計劃中 Extra 列包含 "Using filesort",那么排序就沒有用到索引,filesort 就會執行。

另外,如果 filesort 執行了,優化器跟蹤輸出包括一個 filesort_summary 塊,例如:

"filesort_summary": {"rows": 100,"examined_rows": 100,"number_of_tmp_files": 0,"sort_buffer_size": 25192,"sort_mode": "<sort_key, packed_additional_fields>" }

sort_mode 值提供了一些關于排序緩沖區中的元組的信息。

  • <sort_key, rowid> :它表示排序緩沖區元組是包含原表行的排序鍵值和行ID的對。元組被排序鍵排序,記錄 ID 被用于從表中讀取數據。
  • <sort_key, additional_fields>:它表示排序緩沖區元組包含排序鍵值和查詢涉及到的字段。元組被排序鍵排序,字段值會直接從元組中讀取。
  • <sort_key, packed_additional_fields>:與前面的變體類似,但是附加的列是緊密地打包在一起的,而不是使用固定長度的編碼。

EXPLAIN 不會分辨優化器是否會執行內存中的 filesort 。內存 filesort 的使用可以在優化器的跟蹤報告中看到。

總結

關于 ORDER BY 的優化部分,的確是非常復雜,其中比較重要的是關于 ORDER BY 如何利用索引的具體條件。在某些場合下,ORDER BY 是不會使用到索引的。

總結

以上是生活随笔為你收集整理的MySQL 优化 —— ORDER BY 优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产视频麻豆 | 久久精品国产免费看久久精品 | 天天插天天干天天操 | 欧美激情国产日韩精品一区18 | 波多野在线 | 欧美高清a | 国产一级大片在线观看 | 沟厕沟厕近拍高清视频 | 国产精品高潮呻吟久久av野狼 | 欧美综合在线观看 | 成人免费小视频 | 精品国产第一页 | 激情五月激情综合 | 日韩国产欧美一区二区 | 秋霞欧美一区二区三区视频免费 | 国产伦精品免费视频 | 五月天婷婷色 | 日本一区二区三区网站 | 国产精美视频 | 国产午夜精品久久久久久久 | 日本特黄视频 | 爱情岛论坛成人 | www.蜜桃av | 精品少妇人妻av一区二区三区 | 成人精品久久久午夜福利 | 毛片毛片毛片毛片毛片毛片毛片 | 亚洲精品无码久久久久久久 | 黄色a一片 | 婷婷国产一区二区三区 | 欧美永久免费 | 久久免费的精品国产v∧ | 日本一区二区成人 | 亚洲精品一区二区三区蜜臀 | 日本在线一级片 | 在线一区 | 亚洲免费精品视频在线观看 | 免费看一区二区三区 | 四虎永久地址 | 婷婷丁香激情 | 91插插插影库永久免费 | 亚洲伦理一区 | 亚洲一区亚洲二区 | 久久久免费毛片 | 伊人免费在线观看高清版 | 国产黄a三级三级三级看三级男男 | 欧美日韩国产精品 | 亚洲图片88| 亚洲国产成人91精品 | 校园春色亚洲激情 | 尤物视频一区 | 青青草视频在线观看免费 | 亚洲无人区码一码二码三码的含义 | 日日操天天操 | 亚洲国产成人精品无码区99 | 国产午夜电影在线观看 | 毛片内射久久久一区 | 黄色在线播放网站 | 黄色av免费网站 | 亚洲AV成人午夜无码精品久久 | 麻豆精品视频免费观看 | 99亚洲视频| 深爱激情站 | 日本一区二区免费高清视频 | 成年人网站免费 | 久久亚洲网站 | 久久精品人人做人人爽 | 中文字幕一区日韩 | 亚洲av无码一区二区二三区软件 | 人人人干| 国产在线色视频 | 国产伦精品一区二区三区免费视频 | 国产黄色一级片 | 丁香婷婷亚洲 | 91美女在线视频 | 欧美九九视频 | 爱av在线 | 久久久久久97 | 日本午夜在线视频 | 亚洲av成人精品一区二区三区在线播放 | 蜜桃无码一区二区三区 | 污网站免费看 | 69天堂| 四色成人 | 青青草自拍视频 | 99riAv国产精品无码鲁大师 | 欧美国产一区二区 | 5566毛片 | 中文字幕人妻无码系列第三区 | 三上悠亚一区二区 | 亚洲国产精品一区二区久久hs | 欧美福利影院 | 日免费视频 | 久久疯狂做爰流白浆xx | 免费的黄色网 | 久久久久高潮 | 黄色一级片在线免费观看 | 成人做爰www免费看视频网站 | 日韩黄色在线播放 | 日韩亚洲欧美一区二区 |