一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

通俗易懂講解一條SQL是怎么執(zhí)行的

 昵稱16619343 2019-04-29

MySQL我們可能是使用得最多的數(shù)據(jù)庫(kù)了,但你知道你編寫的SQL語(yǔ)句是怎么樣執(zhí)行的嗎?這篇文章通俗易懂地告訴你!

一條查詢SQL執(zhí)行流程圖如下

本文改編自《高性能Mysql》,煙哥用小說(shuō)的形式來(lái)講這個(gè)內(nèi)容。

序章 自我介紹

我是一條sql,就是一條長(zhǎng)長(zhǎng)的字符串,不要問(wèn)我長(zhǎng)什么樣,因?yàn)槲冶容^傲嬌。

額~~不是我不說(shuō)啊,因?yàn)榧?xì)說(shuō)起來(lái),我可以細(xì)分為DML(Update、Insert、Delete),DDL(表結(jié)構(gòu)修改),DCL(權(quán)限操作),DQL(Select)操作,一個(gè)個(gè)去介紹,我怕大家嫌我煩!
嗯,大家沒(méi)什么意見(jiàn),我繼續(xù)往下自我介紹了~
由于種類太多,這里我只是一條查詢SQL,也就是一句DQL。
客戶端按照Mysql通信協(xié)議,把我發(fā)送到服務(wù)端。
當(dāng)我到達(dá)服務(wù)端后,我會(huì)在一個(gè)單獨(dú)的 線程里進(jìn)行執(zhí)行。服務(wù)端要先…
萬(wàn)萬(wàn)沒(méi)想到,我又被打斷了~好吧,因?yàn)槲以谝粋€(gè)線程里執(zhí)行,總要有辦法能看到線程的執(zhí)行狀態(tài)吧。Mysql提供了下面的命令,給大家查看SHOW [FULL] PROCESSLIST

出來(lái)的結(jié)果是長(zhǎng)下面這樣的

圖里Command這一列,反應(yīng)的就是這個(gè)線程當(dāng)前的執(zhí)行狀態(tài)啦。我在這個(gè)線程的執(zhí)行過(guò)程中,狀態(tài)是會(huì)變化很多次。
你看圖里,有一個(gè)Sleep,這是在告訴你線程正在等待客戶端發(fā)送新的請(qǐng)求。還有一個(gè)為Query,這代表線程正在執(zhí)行查詢或者正在將結(jié)果發(fā)送給客戶端。
至于其他的,還有Locked、Sending data等等,分別代表…
額,好吧,嘮嘮叨叨了一大堆,大家居然木有嫌我煩,嗯,至于其他狀態(tài)的含義大家可以去Mysql官網(wǎng)查詢哦。
嗯,回到剛才的話題。我到達(dá)服務(wù)端后,Mysql要判斷我的前6個(gè)字符是否為select。并且,語(yǔ)句中不帶有SQL_NO_CACHE關(guān)鍵字,如果符合條件,就進(jìn)入查詢緩存。

第一章 我和查詢緩存的那些事

說(shuō)到查詢緩存,它其實(shí)是一個(gè)哈希表,它將執(zhí)行過(guò)的語(yǔ)句及其結(jié)果會(huì)以 key-value 對(duì)的形式,被直接緩存在內(nèi)存中。
它的key是一個(gè)哈希值,是通過(guò)查詢SQL(也就是我)、當(dāng)前要查詢的數(shù)據(jù)庫(kù)、客戶端協(xié)議版本等,生成的一個(gè)哈希值,而它的value自然就是查詢結(jié)果啦。

當(dāng)然,如果我要繞過(guò)查詢緩存,也很簡(jiǎn)單。我可以像下面這么寫:

Select SQL_NO_CACHE * from table也可以將參數(shù)query_cache_type設(shè)置成DEMAND來(lái)繞過(guò)查詢緩存。

可是,有一天查詢緩存悲傷的對(duì)我說(shuō):'你將來(lái)再也看不到我了,我已經(jīng)被歷史淘汰了,Mysql8.0版本開(kāi)始就沒(méi)有我了!'
聽(tīng)到這個(gè)消息后,我表面上故作堅(jiān)強(qiáng)的對(duì)查詢緩存說(shuō):'不要方,大家會(huì)想你的!'
然而,實(shí)際上心里想的是:'嘿嘿嘿,你個(gè)坑爹的,終于不存在了!'大家不要覺(jué)得我太邪惡,畢竟查詢緩存實(shí)在是太不好用了。接下來(lái)我們來(lái)說(shuō)說(shuō)解析器…

萬(wàn)萬(wàn)沒(méi)想到,本來(lái)想糊弄過(guò)去的。結(jié)果…好吧,回到正題,因?yàn)?ul>
  • 只要有對(duì)一個(gè)表的更新,這個(gè)表上所有的查詢緩存都會(huì)被清空

  • SQL任何字符上的不同,如空格,注釋,都會(huì)導(dǎo)致緩存不命中

  • 因此,我能想到用查詢緩存的表,只有一種情況,那就是配置表。其他的業(yè)務(wù)表,根本是無(wú)法利用查詢緩存的特性,或許Mysql團(tuán)隊(duì)也是覺(jué)得查詢緩存的使用場(chǎng)景過(guò)于局限,就無(wú)情的將它剔除。

    第二章 我和分析器的愛(ài)恨情仇

    (本文將解析器和預(yù)處理器統(tǒng)一稱為分析器)
    話說(shuō),我離開(kāi)查詢緩存后,進(jìn)入解析器。
    解析器:'來(lái)來(lái)來(lái),我先對(duì)你進(jìn)行詞法分析,告訴我你長(zhǎng)啥樣?'
    我是下面這樣的

    select username from userinfo

    解析器:'好,好,好。我有兩個(gè)階段,我先對(duì)你進(jìn)行詞法分析,我將你從左到右一個(gè)字符、一個(gè)字符地輸入,然后根據(jù)構(gòu)詞規(guī)則識(shí)別單詞。你將會(huì)生成4個(gè)Token,如下所示。'

    解析器:'接下來(lái)呢,進(jìn)行語(yǔ)法解析,判斷你輸入的這個(gè) SQL 語(yǔ)句是否滿足 MySQL 語(yǔ)法。然后生成下面這樣一顆語(yǔ)法樹(shù)。'

    我:'如果語(yǔ)法不對(duì)呢?'
    解析器:'那你會(huì)收到一個(gè)提示如下!'You have an error in your SQL syntax

    解析器:'順利生成語(yǔ)法樹(shù)以后,我就將你送往預(yù)處理器!'
    預(yù)處理器:'老弟,你來(lái)拉!'
    我:'嗯!'
    預(yù)處理器:'老弟,我來(lái)幫你看看你的列名對(duì)不對(duì),數(shù)據(jù)庫(kù)的這張表里是不是真的有這個(gè)列。再看看表名對(duì)不對(duì),如果不對(duì),你會(huì)看到下面的錯(cuò)誤!'

    Unknown column xxx in ‘where clause’

    預(yù)處理器:'最后我再給你送去做權(quán)限驗(yàn)證,如果你沒(méi)有操作這個(gè)表的權(quán)限,會(huì)報(bào)下面這個(gè)錯(cuò)誤!'

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

    (這個(gè)地方,大家可能有疑問(wèn),因?yàn)橛行┪恼抡f(shuō)是執(zhí)行器做的權(quán)限驗(yàn)證,可以直接拉到本文底部看說(shuō)明)

    最后,這顆語(yǔ)法樹(shù)會(huì)傳遞給優(yōu)化器。

    第三章 我和優(yōu)化器的動(dòng)人過(guò)往

    在告別了解析器后,我進(jìn)入了優(yōu)化器。
    優(yōu)化器大哥:'告訴我,你長(zhǎng)什么樣?。?
    我說(shuō)道:'大哥不要捉急,我是長(zhǎng)這樣的~'(這里優(yōu)化的其實(shí)應(yīng)該是語(yǔ)法樹(shù),我只是為了便于說(shuō)明,才用SQL當(dāng)例子,實(shí)際上是針對(duì)語(yǔ)法樹(shù)進(jìn)行優(yōu)化)

    select t1.*
    from Table1 t1
    inner join Table2 t2
    on t1.CommonID = t2.CommonID
    優(yōu)化器大哥:'我的任務(wù)就是幫你判斷一下怎么樣執(zhí)行更快,比如先查Table1再查Table2,還是先查Table2再查Table1呢?判斷完如何執(zhí)行以后,生成執(zhí)行計(jì)劃就好啦!'
    我很不信任的說(shuō)道:“哼,你就不會(huì)判斷失誤么!”
    優(yōu)化器大哥:'那就要對(duì)SQL進(jìn)行改寫啦,比如你帶了STRAIGHT_JOIN關(guān)鍵字,長(zhǎng)下面這樣'select t1.*
    from Table1 t1
    STRAIGHT_JOIN Table2 t2
    on t1.CommonID = t2.CommonID
    '那我就知道強(qiáng)制先找Table1再關(guān)聯(lián)找Table2啦,類似的例子還有很多,我就不一一列舉了!'
    (STRAIGHT_JOIN功能同join類似,但能讓左邊的表來(lái)驅(qū)動(dòng)右邊的表,能改表優(yōu)化器對(duì)于聯(lián)表查詢的執(zhí)行順序。)

    我說(shuō)道:'哇塞,如何編寫一個(gè)高效的SQL,真是一門學(xué)問(wèn)?。?
    于是,優(yōu)化器大哥將我變身為一個(gè)執(zhí)行計(jì)劃,然后交給執(zhí)行器啦~

    第四章 我和執(zhí)行器的悲情經(jīng)歷

    我:'執(zhí)行器大哥,你是用來(lái)做什么的?'
    執(zhí)行器:'就是根據(jù)執(zhí)行計(jì)劃來(lái)進(jìn)行執(zhí)行查詢啦。我就根據(jù)你的指令,逐條調(diào)用底層存儲(chǔ)引擎,逐步執(zhí)行。' MySQL定義了一系列抽象存儲(chǔ)引擎API,以支持插件式存儲(chǔ)引擎架構(gòu)。Mysql實(shí)現(xiàn)了一個(gè)抽象接口層,叫做handler(sql/handler.h),其中定義了接口函數(shù),比如:,,ha_create等等,存儲(chǔ)引擎需要實(shí)現(xiàn)這些接口才能被系統(tǒng)使用。

    末章 一些感慨

    最后一個(gè)階段,Mysql會(huì)將查詢結(jié)果返回客戶端。
    唯一需要說(shuō)明的是,如果是SELECT類型的SQL,Mysql會(huì)將查詢結(jié)果緩存起來(lái)。至于其他的SQL,就將該表涉及到的查詢緩存清空。

    一些疑問(wèn)

    這里關(guān)于權(quán)限驗(yàn)證究竟在哪個(gè)階段執(zhí)行,大家可能會(huì)有一些疑問(wèn)。
    之前有一個(gè)大牛的文章說(shuō)是權(quán)限驗(yàn)證是在執(zhí)行階段,去執(zhí)行前驗(yàn)證權(quán)限,大家如果看過(guò)他的文章,可能會(huì)有疑問(wèn)。我也不是亂質(zhì)疑人家,畢竟我只是一個(gè)小咖。我在這里只是發(fā)表一下我自己的論點(diǎn),歡迎大家拍磚。

    論點(diǎn)一:權(quán)限驗(yàn)證在執(zhí)行器中判斷從邏輯上說(shuō)不通一條查詢SQL經(jīng)過(guò)查詢緩存、分析器、優(yōu)化器,執(zhí)行器。如果到最后一個(gè)階段執(zhí)行器中才發(fā)現(xiàn)權(quán)限不足、那不是前面一系列流程白做了,Mysql應(yīng)該不至于這么傻吧~

    論點(diǎn)二:同《高性能Mysql》一書內(nèi)容不符該書209頁(yè)有一句話如下圖所示

    該書也指明權(quán)限驗(yàn)證是在預(yù)處理器中執(zhí)行。本文中將預(yù)處理和解析器統(tǒng)一劃分為分析器的范疇。 論點(diǎn)三:同源碼不符我翻看了Mysql5.7.25這個(gè)版本的源碼,其在處理查詢這段的核心代碼如下
    sql_parse.cc文件中,有這么一段代碼如下case SQLCOM_SELECT:
    {
    //省略
    res= select_precheck(thd, lex, all_tables, first_table);
    if (!res)
    res= execute_sqlcom_select(thd, all_tables);
    //省略
    }
    其中是進(jìn)行權(quán)限校驗(yàn)。而優(yōu)化器和執(zhí)行器是在execute_sqlcom_select這個(gè)方法中。
    當(dāng)然,大家有新的見(jiàn)解,歡迎留言。最后轉(zhuǎn)發(fā)到朋友圈是對(duì)我最大的支持!

      本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
      轉(zhuǎn)藏 分享 獻(xiàn)花(0

      0條評(píng)論

      發(fā)表

      請(qǐng)遵守用戶 評(píng)論公約

      類似文章 更多

      成年女人下边潮喷毛片免费| 国产成人精品国产亚洲欧洲| 内射精子视频欧美一区二区| 亚洲天堂有码中文字幕视频| 欧美日韩国产欧美日韩| 日韩不卡一区二区视频| 国产欧美亚洲精品自拍| 日韩国产亚洲一区二区三区| 日韩一区二区三区观看| 成年人黄片大全在线观看| 高清欧美大片免费在线观看| 日本在线不卡高清欧美| 婷婷亚洲综合五月天麻豆 | 激情内射日本一区二区三区| 午夜精品福利视频观看| 国产又粗又猛又大爽又黄| 免费观看一区二区三区黄片| 日韩美成人免费在线视频| 91亚洲人人在字幕国产| 精品人妻av区波多野结依| 亚洲精品中文字幕熟女| 成人你懂的在线免费视频| 国产专区亚洲专区久久| 中文字幕亚洲精品人妻| 国产欧美另类激情久久久| 中文字幕精品一区二区三| 欧美成人免费一级特黄| 91精品蜜臀一区二区三区| 日韩中文字幕欧美亚洲| 五月激情综合在线视频| av在线免费观看在线免费观看| 亚洲第一区欧美日韩在线| 国产高清一区二区白浆| 欧美91精品国产自产| 日韩欧美国产亚洲一区| 亚洲一区二区三区精选| 欧美三级大黄片免费看| 麻豆最新出品国产精品| 色狠狠一区二区三区香蕉蜜桃| 亚洲国产四季欧美一区| 正在播放玩弄漂亮少妇高潮|