<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 中判斷條件的先后順序,會引起索引失效么?

          共 2899字,需瀏覽 6分鐘

           ·

          2020-08-21 01:22

          點擊藍色“有關(guān)SQL”關(guān)注我喲

          加個“星標”,天天與8000人一起快樂成長

          在群里看到一個基礎(chǔ)題,有關(guān)索引的使用。


          題目就在這里,有的朋友說選B,有的選C,有的說題目不嚴謹,還有的說沒答案,都是錯誤的。

          討論了很久,有兩個共性的問題,值得拿出來說下:

          • a=1 and b=1 和 b=1 and a=1 會有效利用 idx(b,a) 嗎?

          • b=1 還會利用索引 idx(a,b)嗎?

          實踐出真知,我就試著上機操作下。

          create?database?factory?;

          use?factory?
          go?

          create?table?dbo.workflow?(?flowid?int,?flowamount?int,?flowcount?int?)

          go?

          先回答第一個問題,判斷條件的順序會影響索引使用嗎

          這兒模擬題目中的?idx(b,a)?索引結(jié)構(gòu)

          create?index?idx_amt_id?on?dbo.workflow(flowamount,flowid)

          模擬?a=1?and?b=1?的查詢

          select?*?from?dbo.workflow?
          where?flowid?=?1?and?flowamount?=?1?

          模擬?b=1?and?a=1?的查詢

          select?*?from?dbo.workflow?
          where?flowamount?=?1?and?flowid?=?1?

          可以看到,當(dāng)表新建,還沒有數(shù)據(jù)時,優(yōu)化器根本不會去判斷用不用索引,而是直接全表掃描。反正就一個數(shù)據(jù)頁。


          當(dāng)我們加點數(shù)據(jù)時,再看看反應(yīng):

          這里不得不再提下 tally table 的用法,實在看不下去利用循環(huán)來生成測試數(shù)據(jù)的方法

          DECLARE?@BEGIN?DATETIME?=?'2010-01-01'

          ????????????????,@END?DATETIME?=?'2017-10-30'

          DECLARE?@INC?INT?;

          SELECT?@INC?=?DATEDIFF(DAY,@BEGIN,@END)



          ;?WITH?

          ????L0?AS?(?

          ????????????SELECT?*?FROM?(VALUES(1),(2),(3))?AS?T(C)?)

          ,????L1?AS?(

          ????????????SELECT?a.C,b.C?AS?BC?FROM?L0?AS?a?cross?join?L0?AS?b?)

          ,????L2?AS?(

          ????????????SELECT?a.C,b.C?AS?BC?FROM?L1?AS?a?cross?join?L1?AS?b?)

          ,????L3?AS?(

          ????????????SELECT?a.C,b.C?AS?BC?FROM?L2?AS?a?cross?join?L2?AS?b?)

          ,????L4?AS?(

          ????????????SELECT?a.C,b.C?AS?BC?FROM?L3?AS?a?cross?join?L3?AS?b?)

          ,????L5?AS?(

          ????????????SELECT?a.C,b.C?AS?BC?FROM?L4?AS?a?cross?join?L4?AS?b?)

          insert?into??dbo.workflow?(flowid,flowamount,flowcount)????????????

          SELECT?TOP?50000?RNK?,?RNK?*?10,?RNK?+?20?

          FROM?

          (

          SELECT?ROW_NUMBER()?OVER(ORDER?BY?(SELECT?NULL))?AS?RNK?

          FROM?L5

          )?M?

          此時表里有5萬條數(shù)據(jù),再看上面兩條查詢的執(zhí)行計劃:

          這兒模擬題目中的?idx(b,a)?索引結(jié)構(gòu)

          create?index?idx_amt_id?on?dbo.workflow(flowamount,flowid)

          模擬?a=1?and?b=1?的查詢

          select?*?from?dbo.workflow?
          where?flowid?=?1?and?flowamount?=?1?

          模擬?b=1?and?a=1?的查詢

          select?*?from?dbo.workflow?
          where?flowamount?=?1?and?flowid?=?1?

          很明顯,都會走索引 idx(b,a) 這種模式,與 b 在前和 a 在前無關(guān)。優(yōu)化器可以優(yōu)化這部分表達式的重組。

          但,是不是所有條件表達式都沒有先后順序要求呢?肯定不是

          只有在相等條件判斷時,先后順序不重要,一旦有表達式用于非等判斷,順序就很重要了,如下:

          select?*?from?dbo.workflow?
          where?flowamount?>?39?and?flowid?=?1?


          select?*?from?dbo.workflow?
          where?flowid?=?1?and?flowamount?>?39??

          這里優(yōu)化器提示(綠色字體部分),建立一個相等判斷條件的索引在前,非等判斷字段在后的索引 (flowid,flowamount)。所以本質(zhì)上,索引結(jié)構(gòu)中字段先后不受制于查詢中相等判斷條件表達式字段的順序,而受制于非等條件判斷表達式。即非等判斷字段(flowamount>39)需要放在相等判斷字段(flowid=1)的后面。

          create?index?idx_id_amtr?on?dbo.workflow(flowid,flowamount)


          select?*?from?dbo.workflow?
          where?flowamount?>?39?and?flowid?=?1?


          select?*?from?dbo.workflow?
          where?flowid?=?1?and?flowamount?>?39??

          再看兩者的執(zhí)行計劃:


          這里就走了我們剛才新建的索引 idx_id_amtr

          第二個問題,b=1 還會利用索引 idx(a,b)嗎?

          在上面的示例中,建立 index(flowamount,flowid) 的索引,那么對應(yīng)到要解決的問題,便是 where flowid = 1 會走 index(flowamount,flowid)的索引嗎?

          select?*?from?dbo.workflow?
          where??flowid?=?1?

          由此可見 b=1 是不會利用索引 idx(a,b) 了。

          注意,或許 oracle, mysql, pg, 等其他數(shù)據(jù)庫會有不同,大家可以嘗試實際操作下,再一起來討論。各自優(yōu)化器的算法不同,優(yōu)化略微有些詫異。不必過于糾結(jié)。



          --完--





          往期精彩:


          本號精華合集(二)

          如何寫好 5000 行的 SQL 代碼

          如何提高閱讀 SQL 源代碼的快感

          我在面試數(shù)據(jù)庫工程師候選人時,常問的一些題

          零基礎(chǔ) SQL 數(shù)據(jù)庫小白,從入門到精通的學(xué)習(xí)路線與書單









          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  亚洲啪啪视频 | 国产在线字幕 | 国产精品高潮呻吟 | 国产美女日逼视频 | 国产免费一区二区三区四区午夜视频 |