<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>

          MySQL之InnoDB存儲(chǔ)引擎:淺談查詢(xún)優(yōu)化

          共 3138字,需瀏覽 7分鐘

           ·

          2021-05-02 16:48

          眾所周知,MySQL中存在所謂的查詢(xún)優(yōu)化器。顧名思義,其可對(duì)用戶(hù)提交的SQL查詢(xún)語(yǔ)句進(jìn)行優(yōu)化,以便可以通過(guò)某種更高效的方式來(lái)執(zhí)行

          abstract.png

          化簡(jiǎn)語(yǔ)句

          查詢(xún)優(yōu)化器最常見(jiàn)的優(yōu)化措施,即是對(duì)我們SQL語(yǔ)句進(jìn)行化簡(jiǎn)

          移除多余括號(hào)

          通常我們?yōu)榱吮苊庥洃浉鞣N操作符的優(yōu)先級(jí),會(huì)在SQL語(yǔ)句中頻繁使用括號(hào)來(lái)避免出錯(cuò)。當(dāng)然,也不用擔(dān)心大量使用括號(hào)會(huì)不會(huì)造成什么性能上的缺陷,因?yàn)椴樵?xún)優(yōu)化器會(huì)移除掉SQL語(yǔ)句中多余的括號(hào)

          例如,下面的SQL表達(dá)式中使用大量的括號(hào)

          ( (b<c AND a=22) OR ( (b=18) AND (c<22) ) )

          查詢(xún)優(yōu)化器移除多余括號(hào),即變?yōu)?/p>

          (b<c AND a=22) OR (b=18 AND c<22)

          Constant Propagation 常量傳播

          字段a與某個(gè)常量進(jìn)行等值查詢(xún),與此同時(shí),其還通過(guò)AND連接了另外一個(gè)表達(dá)式。如果該表達(dá)式中含有a字段,則查詢(xún)優(yōu)化器可將該表達(dá)式中的a字段直接替換為等值查詢(xún)中的常量值。即所謂的Constant Propagation常量傳播

          例如下面的SQL表達(dá)式

          a=5 AND c<a

          則優(yōu)化的結(jié)果為

          a=5 AND c<5

          Equality Propagation 等同性傳播

          若存在多個(gè)字段間的等值查詢(xún)且使用AND進(jìn)行連接,則可使用Equality Propagation等同性傳播進(jìn)行簡(jiǎn)化

          如下面的SQL語(yǔ)句

          a=b AND d=b AND d=996

          則優(yōu)化的結(jié)果為

          a=996 AND b=996 AND d=996

          移除無(wú)用條件

          如果某表達(dá)式結(jié)果恒為T(mén)RUE或FALSE,則查詢(xún)優(yōu)化器會(huì)將其移除進(jìn)行簡(jiǎn)化

          如下面的SQL語(yǔ)句

           (a=123 OR c!=c) OR (69=69 AND d>996)

          則優(yōu)化的結(jié)果為

          a=123 OR d>996

          計(jì)算表達(dá)式

          通常如果表達(dá)式中只包含常量,查詢(xún)優(yōu)化器會(huì)提前進(jìn)行計(jì)算其結(jié)果

          如下面的SQL語(yǔ)句

          d = 34+35

          則優(yōu)化的結(jié)果為

          d = 69

          值得一提的是,如果字段不是以單獨(dú)的形式出現(xiàn)的,而是以函數(shù)等形式出現(xiàn)時(shí),MySQL則不會(huì)對(duì)其進(jìn)行優(yōu)化。示例表達(dá)式如下所示

          -- example 1
          ABS(a) > 996
          -- example 2
          -a < -996

          合并having、where子句

          當(dāng)SQL查詢(xún)語(yǔ)句中沒(méi)有 聚集函數(shù)(例如SUM、MAX等)、GROUP BY子句時(shí),查詢(xún)優(yōu)化器會(huì)對(duì)having、where子句進(jìn)行合并

          常量表檢測(cè)

          MySQL中以下兩種場(chǎng)景的查詢(xún)會(huì)非常快:

          1. 所查數(shù)據(jù)表中最多只有一條數(shù)據(jù)記錄
          2. 對(duì) 主鍵 或 唯一二級(jí)索引 進(jìn)行等值查詢(xún),當(dāng)然對(duì)于后者(唯一二級(jí)索引)需為非NULL值的等值查詢(xún)

          由于InnoDB存儲(chǔ)引擎下關(guān)于表中記錄數(shù)的統(tǒng)計(jì)是不準(zhǔn)確的,故第1點(diǎn)不適用InnoDB存儲(chǔ)引擎。第2點(diǎn)是因?yàn)樵摬樵?xún)最多只會(huì)查到1條記錄。由于在上述兩種場(chǎng)景下,查詢(xún)速度是非常快的,故將它們查詢(xún)時(shí)所用的表稱(chēng)之為constant tables常量表。故查詢(xún)優(yōu)化器在分析一個(gè)SQL查詢(xún)語(yǔ)句時(shí),會(huì)首先去執(zhí)行constant tables常量表的查詢(xún),然后用該查詢(xún)結(jié)果來(lái)替換該SQL查詢(xún)語(yǔ)句中的條件,最后再分析其余表的查詢(xún)成本

          這里假設(shè)有兩張表t1、t2,它們的主鍵字段均為id。其中,t1表中主鍵id字段為234的記錄的age字段為24。則對(duì)于下面SQL查詢(xún)語(yǔ)句而言

          SELECT * FROM t1 INNER JOIN t2 
          ON t1.age = t2.age
          WHERE t1.id = 234;

          t1表即是常量表。故在分析t2表的各種查詢(xún)實(shí)現(xiàn)方式的成本前,會(huì)先執(zhí)行對(duì)t1表的查詢(xún),然后利用該查詢(xún)結(jié)果來(lái)替換相關(guān)條件,則上述SQL語(yǔ)句優(yōu)化結(jié)果如下

          SELECT (從常量表t1中獲取到的記錄的各字段的常量值), t2.* 
          FROM t1 INNER JOIN t2 
          ON t2.age = 24

          外連接消除

          對(duì)于內(nèi)連接而言,驅(qū)動(dòng)表與被驅(qū)動(dòng)表的角色不是固定的,故MySQL可通過(guò)調(diào)整、優(yōu)化連接順序來(lái)選擇查詢(xún)成本最低的方案來(lái)執(zhí)行;而對(duì)于外連接而言,其驅(qū)動(dòng)表與被驅(qū)動(dòng)表的角色卻是固定的。故對(duì)于一個(gè)外連接而言,如果能夠?qū)⑵滢D(zhuǎn)換為內(nèi)連接,則即可進(jìn)一步通過(guò)調(diào)整、優(yōu)化連接順序來(lái)降低查詢(xún)成本。具體地,在外連接查詢(xún)的where子句中如果存在對(duì)被驅(qū)動(dòng)表字段值不為NULL的查詢(xún)條件,即所謂的reject-null空值拒絕,則外連接即可相互轉(zhuǎn)換為內(nèi)連接。關(guān)于這一點(diǎn)其實(shí)也很好理解,因?yàn)樵谕膺B接查詢(xún)中,如果驅(qū)動(dòng)表的記錄在被驅(qū)動(dòng)表中找不到相應(yīng)匹配的記錄,則依然需要將其放到查詢(xún)結(jié)果中,只不過(guò)對(duì)于被驅(qū)動(dòng)表的字段用NULL值填充即可。故一旦外連接查詢(xún)的被驅(qū)動(dòng)表where子句滿(mǎn)足reject-null空值拒絕,外連接即可被消除、優(yōu)化為內(nèi)連接查詢(xún)

          例如對(duì)于下面的左外連接查詢(xún)而言

          select * from stu_info left join stu_score
          on stu_info.id = stu_score.id
          where score > 20;

          由于被驅(qū)動(dòng)表stu_score滿(mǎn)足reject-null空值拒絕條件,則該外連接查詢(xún)可被優(yōu)化為內(nèi)連接查詢(xún)

          select * from stu_info inner join stu_score
          on stu_info.id = stu_score.id
          where score > 20;

          這里,我們亦可通過(guò)查看該外連接查詢(xún)的執(zhí)行計(jì)劃來(lái)進(jìn)行驗(yàn)證

          explain select * from stu_info left join stu_score
          on stu_info.id = stu_score.id
          where score > 20;

          從執(zhí)行計(jì)劃的結(jié)果中,我們可以看出其是將stu_score作為驅(qū)動(dòng)表、stu_info作為被驅(qū)動(dòng)表。換言之,查詢(xún)優(yōu)化器先消除外連接查詢(xún)并將其轉(zhuǎn)換為內(nèi)連接查詢(xún),然后再通過(guò)調(diào)整連接順序來(lái)實(shí)現(xiàn)最低成本的查詢(xún)

          figure 1.png

          參考文獻(xiàn)

          1. MySQL是怎樣運(yùn)行的
          瀏覽 23
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  国产日韩欧美在线 | 国产淫伦久久久久久久 | av资源网站 | 一本色道综合久久欧美日韩精品 | 操逼视频一区二区三区 |