天天看點

表分區的陰暗面(執行計劃)

測試資料

  當然第一步根據CareSon的Demo建立一份測試資料。

  第二步為了做比較的需要,建一個非分區的非聚集索引,Key 和 分區對齊的非聚集索引一樣。

  第三步建議一個非分區表,資料和分區表一樣,我在測試的時候叫Order2

  第四步在Order2建3個索引,1 聚集索引非分區,2.非聚集索引分區,3非聚集索引非分區

疑問

  這樣測試資料就準備全了。CareSon的博文給我幾個問題:1.為啥不走非聚集索引,2.走了索引會怎麼樣,3如果索引是非分區索引呢,4如果表是非分區表,中的分區索引會怎麼樣

測試結果

  根據問題我寫了一下幾個sql和對應執行計劃和結果(性能差距很大是以單看執行計劃就能猜出那個性能比較好):

  1.使用索引提示,強行走分區索引

  

表分區的陰暗面(執行計劃)

(100 行受影響)

表 'Orders'。掃描計數 4,邏輯讀取 286265 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

表 'Worktable'。掃描計數 0,邏輯讀取 0 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

(1 行受影響)

SQL Server 執行時間:

CPU 時間 = 1514 毫秒,占用時間 = 1132 毫秒。

  2.在分區表中不走索引(在這裡表結構要稍微的變動一下,把非聚集索引删除)

表分區的陰暗面(執行計劃)

表 'Orders'。掃描計數 6,邏輯讀取 25229 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

CPU 時間 = 266 毫秒,占用時間 = 513 毫秒。

  3.使用索引提示,強行走非分區索引

表分區的陰暗面(執行計劃)

表 'Orders'。掃描計數 1,邏輯讀取 318 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

CPU 時間 = 0 毫秒,占用時間 = 122 毫秒。

  4.在非分區表中,使用索引提示走分區索引

表分區的陰暗面(執行計劃)

表 'orders2'。掃描計數 4,邏輯讀取 286265 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

CPU 時間 = 1701 毫秒,占用時間 = 1152 毫秒。

  5.非分區表正常運作

表分區的陰暗面(執行計劃)

表 'orders2'。掃描計數 1,邏輯讀取 318 次,實體讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 實體讀取 0 次,lob 預讀 0 次。

CPU 時間 = 0 毫秒,占用時間 = 140 毫秒。

解決問題

  現在結果有了,那麼就來解答先前的幾個問題1.為啥不走非聚集索引,2.走了索引會怎麼樣,3如果索引是非分區索引呢,4如果表是非分區表,中的分區索引會怎麼樣

  1.為啥不走索引呢?

    1和2 對比一下,1中邏輯讀大概是2中的10倍,就算SQL Server 再傻也會用2這個執行計劃。

  2.走了索引會怎麼樣?

    看1的執行時間和執行計劃,走了索引性能很爛

  3.如果索引是非分區索引呢?

    請對比1和3,2和3性能差距不是一點點,那麼就引出另外一個話題,為什麼非分區索引性能比分區的好呢?這個下面再讨論

  4.表如果是非分區表,中的分區索引會怎麼樣?

    對比4和5非常負責任的告訴你,性能很爛。

總結

  現在來說說為什麼非分區索引性能在這裡比分區的好,分區索引是根據分區方案,分别存放,如前面的例子直接使用某個值來過濾,索引查找會掃描所有分區,查詢那些資料,那麼它讀取的頁遠遠大于直接在非聚集索引中seek,自己運作demo,檢視非聚集索引seek左邊的排序,是根據orderdate,id排序,視乎在為了給嵌套循環做準備,之後還要根據datemodified,id排序。非分區索引嚴格按照排序的字段排序,是以看執行計劃的時候看實際相應行數為100,但是看走分區索引的實際相應行數則為170081也就意味着走非分區索引加大了IO,和多餘的計算。恰恰造成查詢偏慢的原因就是因為分區的陰暗面。不恰當的使用分區。CareSon的博文讓我對分區表和索引對齊有了更加深入的認識。