測試資料
當然第一步根據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的博文讓我對分區表和索引對齊有了更加深入的認識。