最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql關(guān)于排序底層原理解析

 更新時(shí)間:2024年03月20日 10:47:14   作者:風(fēng)清揚(yáng)-獨(dú)孤九劍  
這篇文章主要介紹了mysql關(guān)于排序底層原理解析,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

本章詳細(xì)講下排序,排序在我們業(yè)務(wù)開發(fā)非常常見,有對時(shí)間進(jìn)行排序,又對城市進(jìn)行排序的。

不合適的排序,將對系統(tǒng)是災(zāi)難性的,這個(gè)不是危言聳聽。

可能有些人會想,對于排序mysql 是怎么實(shí)現(xiàn)的,它的底層原理是怎么樣的,如果我加上分頁,排序是不是就會快一些。

關(guān)于這些問題,本章詳細(xì)講解。

有人經(jīng)常問我,mysql 優(yōu)化的規(guī)則,總是不假思索的說ESR,E 是 equal ,S是sort 。

可見排序有多么重要,為了講解方便,我先畫個(gè)思維導(dǎo)圖。

上圖標(biāo)的1,2 是mysql 配置文件可以配置的。

可以通過 show variables like 'max_length_for_sort_data'; 可以具體的配置。

從圖上我們可以看到mysql 排序分為全字段排序,和 rowid 。

這是兩大類,里面又分為內(nèi)存排序,文件排序,我將從這2大類4小類講解。

全字段排序

由上圖可以看出 Extra = Using filesort 就表示了排序,但此時(shí)還不能判斷是文件排序還是內(nèi)存排序

可以根據(jù)下面介紹的方法,來確定一個(gè)排序語句是否使用了臨時(shí)文件

/* 打開optimizer_trace,只對本線程有效 */
SET optimizer_trace='enabled=on'; 
?
/* @a保存Innodb_rows_read的初始值 */
select VARIABLE_VALUE into @a from  performance_schema.session_status where variable_name = 'Innodb_rows_read';
?
/* 執(zhí)行語句 */
select city, name,age from t where city='杭州' order by name limit 1000; 
?
/* 查看 OPTIMIZER_TRACE 輸出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G
?
/* @b保存Innodb_rows_read的當(dāng)前值 */
select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';
?
/* 計(jì)算Innodb_rows_read差值 */
select @b-@a;

Number_of_tmp_files>0 就表示文件排序,沒有就表示是內(nèi)存排序。

sort_buffer_size 越小,那么 Number_of_tmp_files 就會越大,文件排序用的是歸并排序,也就是把數(shù)據(jù)分給多個(gè)文件,每個(gè)文件排序后,最終合并一個(gè)文件。

上面sort_mode 可以看到,這是一個(gè)全字段排序,什么是全字段排序,就拿上面這個(gè)sql 語句來說,city ,name,age 都在文件里,對name 進(jìn)行排序

這個(gè)排序的內(nèi)部是這么實(shí)現(xiàn)的:

  • 初始化 sort_buffer,確定放入 name、city、age 這三個(gè)字段;
  • 從索引 city 找到第一個(gè)滿足 city='杭州’ 條件的主鍵 id
  • 到主鍵 id 索引取出整行,取 name、city、age 三個(gè)字段的值,存入 sort_buffer 中;
  • 從索引 city 取下一個(gè)滿足 city='杭州’ 的主鍵 id;
  • 重復(fù)步驟 3、4 直到 city 的值不滿足查詢條件為止
  • 對 sort_buffer 中的數(shù)據(jù)按照字段 name 做快速排序;
  • 按照排序結(jié)果取前 1000 行返回給客戶端。

由此我們發(fā)現(xiàn),排序會對表的所有的記錄進(jìn)行排序,然后在取出1000條

rowid

如果 排序數(shù)據(jù)的長度超過了 max_length_for_sort_data 就是 rowid排序。

排序數(shù)據(jù)的長度就是指拿上面這個(gè)例子說 name、city、age 這三個(gè)字段大于 max_length_for_sort_data 就是rowid 排序。

為什么會這樣的呢,mysql 會盡量用內(nèi)存排序,字段越長,占用空間越大,未了提高排序效率,就會用rowid 排序。

rowid排序的步驟是這樣的:

  • 初始化 sort_buffer,確定放入兩個(gè)字段,即 name 和 id;
  • 從索引 city 找到第一個(gè)滿足 city='杭州’條件的主鍵 id
  • 到主鍵 id 索引取出整行,取 name、id 這兩個(gè)字段,存入 sort_buffer 中;
  • 從索引 city 取下一個(gè)記錄的主鍵 id;
  • 重復(fù)步驟 3、4 直到不滿足 city='杭州’條件為止,
  • 對 sort_buffer 中的數(shù)據(jù)按照字段 name 進(jìn)行排序;
  • 遍歷排序結(jié)果,取前 1000 行,并按照 id 的值回到原表中取出 city、name 和 age 三個(gè)字段返回給客戶端。

我們可以看到 rowid 會多訪問一次表,在mysql 看來,排序的復(fù)雜度高于回表的復(fù)雜度,這也是一種取舍。

綜上可以看出不管是內(nèi)存排序還是文件排序,都是很繁瑣的,那么有沒有對于這個(gè)問題有沒有優(yōu)化點(diǎn)了,在前面我們已經(jīng)講過了,索引一定是有序的,如果我們對city,name 建一個(gè)聯(lián)合索引,就不用mysql 重新排序,因?yàn)樗饕旧砭褪怯行虻摹?/p>

就是如下所示:

alter table t add index city_user(city, name);

但是上面雖然不用mysql 用文件排序,但是還是要回表的,那還有沒有進(jìn)一步的優(yōu)化呢,我們可以考慮用覆蓋索引

如下所示:

alter table t add index city_user_age(city, name, age);

這樣就不用回表了,用explain 來看 Extra using index

大家要綜合考慮吧,索引越多,索引越大,會影響插入的速度的。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MySQL中深分頁LIMIT 100000的優(yōu)化方案

    MySQL中深分頁LIMIT 100000的優(yōu)化方案

    在實(shí)際項(xiàng)目中,分頁查詢是最常見的 SQL 場景之一,但隨著業(yè)務(wù)數(shù)據(jù)量不斷增長,我們經(jīng)常會遇到深分頁的請求,本文將帶大家理解 MySQL 深分頁的本質(zhì)以及掌握高性能替代方案,感興趣的可以了解下
    2025-11-11
  • MySQL虛擬列的使用示例

    MySQL虛擬列的使用示例

    虛擬列是MySQL中的一種特殊列,它不存儲在表中,而是在查詢時(shí)動態(tài)計(jì)算生成,虛擬列可以提高查詢效率、減少存儲需求、確保數(shù)據(jù)一致性、簡化查詢和保護(hù)敏感數(shù)據(jù),感興趣的可以了解一下
    2024-11-11
  • win10下安裝mysql8.0.23 及 “服務(wù)沒有響應(yīng)控制功能”問題解決辦法

    win10下安裝mysql8.0.23 及 “服務(wù)沒有響應(yīng)控制功能”問題解決辦法

    這篇文章主要介紹了win10下安裝mysql8.0.23 及 “服務(wù)沒有響應(yīng)控制功能”問題解決辦法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • MySQL查看每個(gè)分區(qū)的數(shù)據(jù)量的查詢方法

    MySQL查看每個(gè)分區(qū)的數(shù)據(jù)量的查詢方法

    在MySQL中,分區(qū)表是一種將數(shù)據(jù)分割成更小、更易管理的部分的方法,通過分區(qū),可以顯著提高查詢性能和數(shù)據(jù)管理效率,在實(shí)際應(yīng)用中,了解每個(gè)分區(qū)中的數(shù)據(jù)量有助于優(yōu)化和監(jiān)控?cái)?shù)據(jù)庫性能,本文將介紹如何查看MySQL中每個(gè)分區(qū)的數(shù)據(jù)量,需要的朋友可以參考下
    2025-07-07
  • mysql 忘記密碼的解決方法(linux和windows小結(jié))

    mysql 忘記密碼的解決方法(linux和windows小結(jié))

    下面是linux和windows下mysql丟失密碼的解決辦法
    2008-12-12
  • Mysql修改字段類型、長度及添加刪除列實(shí)例代碼

    Mysql修改字段類型、長度及添加刪除列實(shí)例代碼

    在MySQL中可以使用ALTER?TABLE語句來修改表結(jié)構(gòu),包括添加自增屬性,下面這篇文章主要給大家介紹了關(guān)于Mysql修改字段類型、長度及添加刪除列的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Mysql縱表轉(zhuǎn)換為橫表的方法及優(yōu)化教程

    Mysql縱表轉(zhuǎn)換為橫表的方法及優(yōu)化教程

    在應(yīng)用中為了從不同的視圖去分析數(shù)據(jù),會使用不同的方案去查詢數(shù)據(jù)庫,橫表和縱表的相互轉(zhuǎn)換就是其中一個(gè)常見的情景,這篇文章主要給大家介紹了關(guān)于Mysql縱表轉(zhuǎn)換為橫表的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • MYSQL之Doublewrite?Buffer雙寫緩存區(qū)詳解

    MYSQL之Doublewrite?Buffer雙寫緩存區(qū)詳解

    由于MySQL頁(16KB)與Linux文件系統(tǒng)頁(4KB)不匹配,可能導(dǎo)致部分頁寫入損壞,Redo日志無法修復(fù),Doublewrite?Buffer通過內(nèi)存+磁盤雙緩沖確保數(shù)據(jù)可靠性,與Redo日志協(xié)作實(shí)現(xiàn)故障恢復(fù),相關(guān)參數(shù)用于配置
    2025-08-08
  • 一文帶你解鎖MySQL實(shí)現(xiàn)行轉(zhuǎn)列的完整方法

    一文帶你解鎖MySQL實(shí)現(xiàn)行轉(zhuǎn)列的完整方法

    MySQL的行轉(zhuǎn)列,不是簡單的語法堆砌,而是對數(shù)據(jù)結(jié)構(gòu)深刻理解后的重構(gòu),這篇文章主要介紹了MySQL實(shí)現(xiàn)行轉(zhuǎn)列的完整方法,有需要的小伙伴可以了解下
    2026-01-01
  • 分享101個(gè)MySQL調(diào)試與優(yōu)化技巧

    分享101個(gè)MySQL調(diào)試與優(yōu)化技巧

    隨著越來越多的數(shù)據(jù)庫驅(qū)動的應(yīng)用程序,人們一直在推動MySQL發(fā)展到它的極限。這里是101條調(diào)節(jié)和優(yōu)化MySQL安裝的技巧。一些技巧是針對特定的安裝環(huán)境的,但這些思路是通用的。我已經(jīng)把他們分成幾類,來幫助你掌握更多MySQL的調(diào)節(jié)和優(yōu)化技巧
    2017-05-05

最新評論

北川| 东丽区| 资溪县| 藁城市| 麻阳| 中西区| 佛山市| 定兴县| 乡宁县| 平顺县| 嘉峪关市| 石首市| 四子王旗| 伊金霍洛旗| 伊川县| 台州市| 应用必备| 永新县| 铁岭县| 神木县| 都匀市| 徐闻县| 神池县| 洞口县| 阿荣旗| 静安区| 南召县| 沧州市| 射阳县| 湖口县| 蓬安县| 庆城县| 崇文区| 呼和浩特市| 平果县| 盐亭县| 韶山市| 通城县| 华安县| 周宁县| 汝阳县|