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

歡迎訪問 生活随笔!

生活随笔

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

数据库

一条查询SQL的执行流程

發(fā)布時間:2023/12/14 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一条查询SQL的执行流程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

查詢SQL的執(zhí)行過程

當希望Mysql能夠高效的執(zhí)行的時候,最好的辦法就是清楚的了解Mysql是如何執(zhí)行查詢的,只有更加全面的了解SQL執(zhí)行的每一個過程,才能更好的進行SQl的優(yōu)化。

當執(zhí)行一條查詢的SQl的時候大概發(fā)生了一下的步驟:

  • 客戶端發(fā)送查詢語句給服務(wù)器。
  • 服務(wù)器首先檢查緩存中是否存在該查詢,若存在,返回緩存中存在的結(jié)果。若是不存在就進行下一步。
  • 服務(wù)器進行SQl的解析、語法檢測和預(yù)處理,再由優(yōu)化器生成對應(yīng)的執(zhí)行計劃。
  • Mysql的執(zhí)行器根據(jù)優(yōu)化器生成的執(zhí)行計劃執(zhí)行,調(diào)用存儲引擎的接口進行查詢。
  • 服務(wù)器將查詢的結(jié)果返回客戶端。
  • Mysql的執(zhí)行的流程

    ?

    ?

    Mysql的執(zhí)行的流程圖如下圖所示:

    這里以一個實例進行說明Mysql的的執(zhí)行過程,新建一個User表,如下:

    // 新建一個表 DROP TABLE IF EXISTS User; CREATE TABLE `User` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(10) DEFAULT NULL,`age` int DEFAULT 0,`address` varchar(255) DEFAULT NULL,`phone` varchar(255) DEFAULT NULL,`dept` int,PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;// 并初始化數(shù)據(jù),如下 INSERT INTO User(name,age,address,phone,dept)VALUES('張三',24,'北京','13265543552',2); INSERT INTO User(name,age,address,phone,dept)VALUES('張三三',20,'北京','13265543557',2); INSERT INTO User(name,age,address,phone,dept)VALUES('李四',23,'上海','13265543553',2); INSERT INTO User(name,age,address,phone,dept)VALUES('李四四',21,'上海','13265543556',2); INSERT INTO User(name,age,address,phone,dept)VALUES('王五',27,'廣州','13265543558',3); INSERT INTO User(name,age,address,phone,dept)VALUES('王五五',26,'廣州','13265543559',3); INSERT INTO User(name,age,address,phone,dept)VALUES('趙六',25,'深圳','13265543550',3); INSERT INTO User(name,age,address,phone,dept)VALUES('趙六六',28,'廣州','13265543561',3); INSERT INTO User(name,age,address,phone,dept)VALUES('七七',29,'廣州','13265543562',4); INSERT INTO User(name,age,address,phone,dept)VALUES('八八',23,'廣州','13265543563',4); INSERT INTO User(name,age,address,phone,dept)VALUES('九九',24,'廣州','13265543564',4);12345678910111213141516171819202122232425

    現(xiàn)在針對這個表發(fā)出一條SQl查詢:查詢每個部門中25歲以下的員工個數(shù)大于3的員工個數(shù)和部門編號,并按照人工個數(shù)降序排序和部門編號升序排序的前兩個部門。

    SELECT dept,COUNT(phone) AS num FROM User WHERE age< 25 GROUP BY dept HAVING num >= 3 ORDER BY num DESC,dept ASC LIMIT 0,2; 1

    執(zhí)行連接器

    開始執(zhí)行這條sql時,會檢查該語句是否有權(quán)限,若是沒有權(quán)限就直接返回錯誤信息,有權(quán)限會進行下一步,校驗權(quán)限的這一步是在圖一的連接器進行的,對連接用戶權(quán)限的校驗。

    執(zhí)行檢索內(nèi)存

    相連建立之后,履行查詢語句的時候,會先行檢索內(nèi)存,Mysql會先行冗余這個sql與否履行過,以此Key-Value的形式平緩適用內(nèi)存中,Key是檢索預(yù)定,Value是結(jié)果集。

    假如內(nèi)存key遭擊中,便會間接回到給客戶端,假如沒命中,便會履行后續(xù)的操作,完工之后亦會將結(jié)果內(nèi)存上去,當下一次進行查詢的時候也是如此的循環(huán)操作。

    執(zhí)行分析器

    分析器主要有兩步:(1)詞法分析(2)語法分析

    詞法分析主要執(zhí)行提煉關(guān)鍵性字,比如select,提交檢索的表,提交字段名,提交檢索條件。語法分析主要執(zhí)行辨別你輸出的sql與否準確,是否合乎mysql的語法。

    當Mysql沒有命中內(nèi)存的時候,接著執(zhí)行的是 FROM student 負責把數(shù)據(jù)庫的表文件加載到內(nèi)存中去,WHERE age< 60,會把所示表中的數(shù)據(jù)進行過濾,取出符合條件的記錄行,生成一張臨時表,如下圖所示。

    GROUP BY dept?會把上圖的臨時表分成若干臨時表,切分的過程如下圖所示:


    查詢的結(jié)果只有部門2和部門3才有符合條件的值,生成如上兩圖的臨時表。接著執(zhí)行SELECT后面的字段,SELECT后面可以是表字段也可以是聚合函數(shù)。

    這里SELECT的情況與是否存在GROUP BY有關(guān),若是不存在Mysql直接按照上圖內(nèi)存中整列讀取。若是存在分別SELECT臨時表的數(shù)據(jù)。

    最后生成的臨時表如下圖所示:

    緊接著執(zhí)行HAVING num>2過濾員工數(shù)小于等于2的部門,對于WHERE和HAVING都是進行過濾,那么這兩者有什么不同呢?

    第一點是WHERE后面只能對表字段進行過濾,不能使用聚合函數(shù),而HAVING可以過濾表字段也可以使用聚合函數(shù)進行過濾。

    第二點是WHERE是對執(zhí)行from USer操作后,加載表數(shù)據(jù)到內(nèi)存后,WHERE是對原生表的字段進行過濾,而HAVING是對SELECT后的字段進行過濾,也就是WHERE不能使用別名進行過濾。

    因為執(zhí)行WHERE的時候,還沒有SELECT,還沒有給字段賦予別名。接著生成的臨時表如下圖所示:

    最后在執(zhí)行ORDER BY后面的排序以及l(fā)imit0,2取得前兩個數(shù)據(jù),因為這里數(shù)據(jù)比較少,沒有體現(xiàn)出來。最后生成得結(jié)果也是如上圖所示。接著判斷這個sql語句是否有語法錯誤,關(guān)鍵性詞與否準確等等。

    執(zhí)行優(yōu)化器

    查詢優(yōu)化器會將解析樹轉(zhuǎn)化成執(zhí)行計劃。一條查詢可以有多種執(zhí)行方法,最后都是返回相同結(jié)果。優(yōu)化器的作用就是找到這其中最好的執(zhí)行計劃。

    生成執(zhí)行計劃的過程會消耗較多的時間,特別是存在許多可選的執(zhí)行計劃時。如果在一條SQL語句執(zhí)行的過程中將該語句對應(yīng)的最終執(zhí)行計劃進行緩存。

    當相似的語句再次被輸入服務(wù)器時,就可以直接使用已緩存的執(zhí)行計劃,從而跳過SQL語句生成執(zhí)行計劃的整個過程,進而可以提高語句的執(zhí)行速度。


    MySQL使用基于成本的查詢優(yōu)化器。它會嘗試預(yù)測一個查詢使用某種執(zhí)行計劃時的成本,并選擇其中成本最少的一個。

    執(zhí)行執(zhí)行器

    由優(yōu)化器生成得執(zhí)行計劃,交由執(zhí)行器進行執(zhí)行,執(zhí)行器調(diào)用存儲引擎得接口,存儲引擎獲取數(shù)據(jù)并返回,結(jié)束整個查詢得過程。

    這里之講解了select的過程,對于update這些修改數(shù)據(jù)或者刪除數(shù)據(jù)的操作,會涉及到事務(wù),會使用兩個日志模塊,redo log和binlog日志。具體對這兩個日志的介紹請看著一篇文章。

    以前的Mysql的默認存儲引擎MyISAM引擎是沒redo log的,而現(xiàn)在的默認存儲引擎InnoDB引擎便是透過redo 復(fù)雜度來擁護事務(wù)的,保證事務(wù)能夠準確的回滾或者提交,保證事務(wù)的ACID。

    1、一條查詢SQL執(zhí)行流程圖

    ? ? ?

    2、查詢SQL執(zhí)行流程之發(fā)送SQL請求

    (1)客戶端按照Mysql通信協(xié)議將SQL發(fā)送到服務(wù)端,SQL到達服務(wù)端后,服務(wù)端會單起一個線程執(zhí)行SQL。

    (2)執(zhí)行時Mysql首先判斷SQL的前6個字符是否為select。并且語句中是否帶有SQL_NO_CACHE關(guān)鍵字,如果沒有則進入查詢緩存。

    3、查詢SQL執(zhí)行流程之查詢緩存

    查詢緩存說白了就是一個哈希表,將執(zhí)行過的語句及其結(jié)果以鍵值對的格式緩存到內(nèi)存中。其中key是一個哈希值,由查詢SQL、當前要查詢的數(shù)據(jù)庫、客戶端協(xié)議版本等生成的,value就是查詢結(jié)果。如果要繞過查詢緩存,可以在SQL中加SQL_NO_CACHE字段,如:

    SELECT SQL_NO_CACHE * FROM table

    注:Mysql8.0版本開始取消查詢緩存

    4、查詢SQL執(zhí)行流程之解析器

    解析器執(zhí)行流程分為兩個階段,詞法解析和語法解析

    (1)首先對SQL詞法進行分析,將SQL從左到右一個字符、一個字符地輸入,然后根據(jù)構(gòu)詞規(guī)則識別單詞。將會生成4個Token,如下所示:

    ?

    (2)然后對SQL語法進行解析,判斷客戶端傳入的SQL語句是否滿足Mysql語法。此時會生成一顆語法樹,如下所示:

    ?

    如果語法不對,將會收到如下提示

    You have an error in your SQL syntax

    ?如果解析器順利生成語法樹,就會將SQL送發(fā)到預(yù)處理器

    5、查詢SQL執(zhí)行流程之預(yù)處理器

    預(yù)處理器主要做兩件事情,查看SQL中列名是否正確和權(quán)限驗證

    (1)首先判斷SQL語句中的列名是否存在于數(shù)據(jù)表中,再看看表名是否正確,如果不對,將返回如下錯誤提示

     Unknown?column?xxx?in?‘where?clause’

    (2)預(yù)處理器對SQL進行權(quán)限驗證,判斷SQL是否有操作這個表的權(quán)限,若沒有,則會返回如下錯誤信息

    ERROR 1142 (42000): SELECT command denied to user 'root'@'localhost' for table 'xxx'

    ?一切驗證通過后將語法樹傳遞給優(yōu)化器

    6、查詢SQL執(zhí)行流程之優(yōu)化器

    優(yōu)化器的任務(wù)就是對SQL語句進行優(yōu)化,達到最快的執(zhí)行效果,優(yōu)化器對SQL優(yōu)化完成后會將SQL變成一個執(zhí)行計劃交給執(zhí)行器

    7、查詢SQL執(zhí)行流程之執(zhí)行器

    執(zhí)行器就是根據(jù)執(zhí)行計劃來進行執(zhí)行查詢, 根據(jù)SQL的指令,逐條調(diào)用底層存儲引擎,逐步執(zhí)行。

    總結(jié)

    以上是生活随笔為你收集整理的一条查询SQL的执行流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。