<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SQL查詢的底層運行原理分析

          共 3547字,需瀏覽 8分鐘

           ·

          2020-08-27 07:09


          點擊上方數(shù)據(jù)管道”,選擇“置頂星標(biāo)”公眾號

          干貨福利,第一時間送達

          SQL 語言無處不在。SQL 已經(jīng)不僅僅是技術(shù)人員的專屬技能了,似乎人人都會寫SQL,就如同人人都是產(chǎn)品經(jīng)理一樣。如果你是做后臺開發(fā)的,那么CRUD就是家常便飯。如果你是做數(shù)倉開發(fā)的,那么寫SQL可能占據(jù)了你的大部分工作時間。我們在理解 SELECT 語法的時候,還需要了解 SELECT 執(zhí)行時的底層原理。只有這樣,才能讓我們對 SQL 有更深刻的認(rèn)識。本文分享將逐步分解SQL的執(zhí)行過程,剖析其底層運行原理,希望對你有所幫助。

          數(shù)據(jù)準(zhǔn)備

          本文旨在說明SQL查詢的執(zhí)行過程,不會涉及太復(fù)雜的SQL操作,主要涉及兩張表:citizencity,具體數(shù)據(jù)如下所示:

          CREATE?TABLE?citizen?(?
          ????name?CHAR?(?20?),?
          ????city_id?INT?(?10?)?
          );


          CREATE?TABLE?city?(
          ????city_id?INT?(?10?),?
          ????city_name?CHAR?(?20?)?
          );

          INSERT?INTO?city
          VALUES
          ?(?1,?"上海"?),
          ?(?2,?"北京"?),
          ?(?3,?"杭州"?);
          ?
          ?
          INSERT?INTO?citizen
          VALUES
          ("tom",3),
          ("jack",2),
          ("robin",1),
          ("jasper",3),
          ("kevin",1),
          ("rachel",2),
          ("trump",3),
          ("lilei",1),
          ("hanmeiei",1);

          查詢執(zhí)行順序

          本文所涉及的查詢語句如下,主要是citizen表與city表進行join,然后篩掉city_name != "上海"的數(shù)據(jù),接著按照city_name進行分組,統(tǒng)計每個城市總?cè)藬?shù)大于2的城市,具體如下:

          查詢語句

          SELECT?
          ????city.city_name?AS?"City",
          ????COUNT(*)?AS?"citizen_cnt"
          FROM?citizen
          ??JOIN?city?ON?citizen.city_id?=?city.city_id?
          WHERE?city.city_name?!=?'上海'
          GROUP?BY?city.city_name
          HAVING?COUNT(*)?>=?2
          ORDER?BY?city.city_name?ASC
          LIMIT?2

          執(zhí)行步驟

          上面SQL查詢語句的書寫書序是:

          SELECT?...?FROM?...?WHERE?...?GROUP?BY?...?HAVING?...?ORDER?BY?...

          但是執(zhí)行順序并不是這樣,具體的執(zhí)行順序如下步驟所示:

          • 1.獲取數(shù)據(jù) (From, Join)
          • 2.過濾數(shù)據(jù) (Where)
          • 3.分組 (Group by)
          • 4.分組過濾 (Having)
          • 5.返回查詢字段 (Select)
          • 6.排序與分頁 (Order by & Limit / Offset)

          執(zhí)行的底層原理

          其實上面所說的SQL執(zhí)行順序就是所謂的底層原理,當(dāng)我們在執(zhí)行SELECT語句時,每個步驟都會產(chǎn)生一張虛擬表(virtual table),在執(zhí)行下一步驟時,會將該虛擬表作為輸入。指的注意的是,這些過程是對用戶透明的。

          你可以注意到,SELECT 是先從FROM 這一步開始執(zhí)行的。在這個階段,如果是多張表進行JOIN,還會經(jīng)歷下面的幾個步驟:

          獲取數(shù)據(jù) (From, Join)

          • 首先會通過 CROSS JOIN 求笛卡爾積,相當(dāng)于得到虛擬表 vt1-1;

          • 接著通過ON 條件進行篩選,虛擬表 vt1-1 作為輸入,輸出虛擬表 vt1-2;

          • 添加外部行。我們使用的是左連接、右鏈接或者全連接,就會涉及到外部行,也就是在虛擬表 vt1-2 的基礎(chǔ)上增加外部行,得到虛擬表 vt1-3

          過濾數(shù)據(jù) (Where)

          經(jīng)過上面的步驟,我們得到了一張最終的虛擬表vt1,在此表之上作用where過濾,通過篩選條件過濾掉不滿足條件的數(shù)據(jù),從而得到虛擬表vt2。

          分組 (Group by)

          經(jīng)過where過濾操作之后,得到vt2。接下來進行GROUP BY操作,得到中間的虛擬表vt3。

          分組過濾 (Having)

          在虛擬表vt3的基礎(chǔ)之上,使用having過濾掉不滿足條件的聚合數(shù)據(jù),得到vt4。

          返回查詢字段 (Select)

          當(dāng)我們完成了條件篩選部分之后,就可以篩選表中提取的字段,也就是進入到 SELECT 和 DISTINCT 階段。首先在 SELECT 階段會提取目標(biāo)字段,然后在 DISTINCT 階段過濾掉重復(fù)的行,分別得到中間的虛擬表 vt5-1 和 vt5-2。

          排序與分頁 (Order by & Limit / Offset)

          當(dāng)我們提取了想要的字段數(shù)據(jù)之后,就可以按照指定的字段進行排序,也就是 ORDER BY 階段,得到虛擬表 vt6。最后在 vt6 的基礎(chǔ)上,取出指定行的記錄,也就是 LIMIT 階段,得到最終的結(jié)果,對應(yīng)的是虛擬表 vt7

          詳細(xì)執(zhí)行步驟分析

          Step 1:獲取數(shù)據(jù) (From, Join)

          FROM?citizen
          JOIN?city?

          該過程的第一步是執(zhí)行From子句中的語句,然后執(zhí)行Join子句。這些操作的結(jié)果是得到兩個表的笛卡爾積。

          namecity_idcity_idcity_name
          tom31上海
          tom32北京
          tom33杭州
          jack21上海
          jack22北京
          jack23杭州
          robin11上海
          robin12北京
          robin13杭州
          jasper31上海
          jasper32北京
          jasper33杭州
          kevin11上海
          kevin12北京
          kevin13杭州
          rachel21上海
          rachel22北京
          rachel23杭州
          trump31上海
          trump32北京
          trump33杭州
          lilei11上海
          lilei12北京
          lilei13杭州
          hanmeiei11上海
          hanmeiei12北京
          hanmeiei13杭州

          在FROM和JOIN執(zhí)行結(jié)束之后,會按照J(rèn)OIN的ON條件,篩選所需要的行

          ON?citizen.city_id?=?city.city_id
          namecity_idcity_idcity_name
          tom33杭州
          jack22北京
          robin11上海
          jasper33杭州
          kevin11上海
          rachel22北京
          trump33杭州
          lilei11上海
          hanmeiei11上海

          Step 2:過濾數(shù)據(jù) (Where)

          獲得滿足條件的行后,將傳遞給Where子句。這將使用條件表達式評估每一行。如果行的計算結(jié)果不為true,則會將其從集合中刪除。

          WHERE?city.city_name?!=?'上海'
          namecity_idcity_idcity_name
          tom33杭州
          jack22北京
          jasper33杭州
          rachel22北京
          trump33杭州

          Step 3:分組 (Group by)

          下一步是執(zhí)行Group by子句,它將具有相同值的行分為一組。此后,將按組對所有Select表達式進行評估,而不是按行進行評估。

          GROUP?BY?city.city_name
          GROUP_CONCAT(citizen.name)city_idcity_name
          jack,rachel2北京
          tom,jasper,trump3杭州

          Step 4:分組過濾 (Having)

          對分組后的數(shù)據(jù)使用Having子句所包含的謂詞進行過濾

          HAVING?COUNT(*)?>=?2

          Step 5:返回查詢字段 (Select)

          在此步驟中,處理器將評估查詢結(jié)果將要打印的內(nèi)容,以及是否有一些函數(shù)要對數(shù)據(jù)運行,例如Distinct,Max,Sqrt,Date,Lower等等。本案例中,SELECT子句只會打印城市名稱和其對應(yīng)分組的count(*)值,并使用標(biāo)識符“ City”作為city_name列的別名。

          SELECT?
          ????city.city_name?AS?"City",
          ?COUNT(*)?AS?"citizen_cnt"
          citycitizen_cnt
          北京2
          杭州3

          Step 6:排序與分頁 (Order by & Limit / Offset)

          查詢的最后處理步驟涉及結(jié)果集的排序與輸出大小。在我們的示例中,按照字母順序升序排列,并輸出兩條數(shù)據(jù)結(jié)果。

          ORDER?BY?city.city_name?ASC
          LIMIT?2
          citycitizen_cnt
          北京2
          杭州3

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操人无码| 国产美女做爱A片是免费 | 黄色成人大片 | 久黄色视频 | 日本特黄一级 |