SQL Server創建複合索引時,複合索引列順序對查詢的性能影響

来源:http://www.cnblogs.com/wy123/archive/2016/06/21/5604400.html
-Advertisement-
Play Games

說說複合索引 寫索引的博客太多了,一直不想動手寫,有一下兩個原因: 一是覺得有炒剩飯的嫌疑,有兄弟曾說:索引嗎,只要在查詢條件上建索引就行了,真的可以這麼暴力嗎? 二來覺得,索引是個非常大的話題,很難概括出所有的情況,你不整齣點新意來,倒是有抄襲照搬的嫌疑 既然寫了,就寫一點稍微不一樣的東西出來, ...


 

 說說複合索引

寫索引的博客太多了,一直不想動手寫,有一下兩個原因:
一是覺得有炒剩飯的嫌疑,有兄弟曾說:索引嗎,只要在查詢條件上建索引就行了,真的可以這麼暴力嗎?
二來覺得,索引是個非常大的話題,很難概括出所有的情況,你不整齣點新意來,倒是有抄襲照搬的嫌疑

既然寫了,就寫一點稍微不一樣的東西出來,
好了,廢話打住,開搞

 

搭建測試環境:

創建一張表,模擬實際業務中的一個表,往裡面填入數據,
時間欄位上,相對按照時間均勻地填充,其他欄位以GUID填充

Create table BusinessInfoTable
(
    BuniessCode1 varchar(50),
    BuniessCode2 varchar(50),
    BuniessCode3 varchar(50),
    BuniessCode4 varchar(50),
    BuniessStatus1 tinyint,
    BuniessStatus2 tinyint,
    BuniessDateTime1 Datetime,
    BuniessDateTime2 Datetime,
    OtherColumn1 varchar(50),
    OtherColumn2 varchar(50),
    OtherColumn3 varchar(50)
)



declare @i int=0
while @i<1000000
begin
    insert into BusinessInfoTable 
    values 
    (
        NEWID(),NEWID(),NEWID(),NEWID(),RAND()*100,RAND()*100,
        DATEADD(MI,@i,GETDATE()),DATEADD(MI,@i,GETDATE()),NEWID(),NEWID(),NEWID()
    )
    set @i=@i+1
end

現在有這麼一個查詢(實際上查詢遠比這個複雜,我簡化一點,不要說我刻意造環境)

    select OtherColumn2,
           BuniessStatus1,
           BuniessStatus2,
           BuniessDateTime1,
           BuniessDateTime2
    from BusinessInfoTable 
    where  BuniessDateTime1 between '2016-6-21' and '2016-6-28'
        and BuniessDateTime2 between '2016-6-21' and '2016-6-28'
        and BuniessStatus1    =    55
        and BuniessStatus2    =    66

鄭重的說明一點:

暫時不考慮聚集索引,畢竟一個表上只能有一個聚集索引,
別人也不是傻子,不會輕易去建聚集索引,聚集索引早被占用了
既然被占用了,我的原則是一般不去動別人現有的東西的,比如別人建了聚集索引,你給人家刪了,根據自己的情況建聚集索引
這不是找罵麽


有經驗的你一定考慮符合索引了,同時考慮到為避免Key Lookup導致的書簽查找,我們把查詢索要的OtherColumn2列include進來
比如這樣

CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable 
(BuniessStatus1,BuniessStatus2,BuniessDateTime1,BuniessDateTime2)
INCLUDE(OtherColumn2)

 

或者這樣,只是索引列順序不一樣

CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable
(BuniessDateTime1,BuniessDateTime2,BuniessStatus1,BuniessStatus2)
INCLUDE(OtherColumn2)

 

當然可以隨意調整四個列的順序,我就不過多地做演示了,有興趣的自己試

這裡的前導列的順序並不會影響到索引的使用,查詢的時候都是非聚集索引Seek,絕對的

那麼問題來了,完全一樣的查詢條件,結果一樣,使用不同的索引,索引的區別僅僅是列順序不一樣,其代價一樣嗎,先猜測一下,有區別嗎?

 

 

  同樣查詢,使用不同索引的結果(分別是上面的IDX_1和IDX_2):

下麵看圖說話

看看IO情況

 

原因分析

  看來是有點差別吧,好似乎這個差別還真不小(以往寫文章,我測試環境弄不好,對比出來的效果不明顯,感覺沒啥說服力,這次對比還是比較明顯的)

  究竟原因在何?

  索引是以平衡樹(B樹)的方式存在的,複合索引的列的順序決定了B樹的信息的存儲的順序

  如果是以BuniessStatus1列為前導列,因為BuniessStatus1分佈的範圍(相對)較小,

  這樣在查詢的時候通過BuniessStatus1=55就可以過濾出來一個比較小的結果集,後面依次用其他條件過濾就相對較快了

  比如BuniessStatus1=55過濾出來符合條件的數據有5條,

  加上BuniessStatus2 BuniessDateTime1 BuniessDateTime2 這三個條件再過濾,出來一條數據。

 

  如果BuniessDateTime1 是索引的前導列,用BuniessDateTime1 between '2016-6-21' and '2016-6-28'過濾

  可能會有10000條數據,然後依次再用 BuniessDateTime2,BuniessStatus1, BuniessStatus2過濾

  最後也只有一條符合條件的數據。

   差別就在於:一開始的過濾條件,決定了查詢多少page初步確定滿足條件的數據,再進一步的進行過濾

  如果最開始就相對精確地確定了滿足查詢條件的數據範圍,後面可以通過相對較小的代價來最終確認出滿足條件的數據

  如果最開始相對模糊地卻確定了滿足查詢條件的數據範圍,那麼這個過程的代價就相對比較大,雖然後面通過每一個條件的過,結果是一樣的

 

  當然這種索引的建立跟數據分佈有關,

  但是,我沒有下結論說,複合索引一定要按照什麼什麼順序來是最好的

  還是那句話:具體問題具體分析,避免經驗主義,沒有一刀切的手段可以解決所有的問題。

 

總結:

  本文通過一個簡單的例子,分析了創建符合索引時,列的順序對查詢的影響,說明在創建索引的時候,不僅僅要考慮在哪些列上創建索引,同時也要註意到,索引列的順序,是否會對查詢產生影響。避免一說到索引,就是“在查詢條件上建索引”的暴力做法。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在同組項目進行共用時,容易把本地的配置文件比如*.iml等文件上傳至共用伺服器,這樣會對隊友造成巨大的麻煩,為瞭解決這個問題,可以使用下麵方法解決,下麵以上傳到伺服器的app.iml文件為例。 一、在AS的Setting中取消忽略文件尾碼".iml"; 二、在Windows目錄中找到當前項目下的"a ...
  • 自己為什麼要學android 本人作為應屆畢業生,自己進入社會前做過好多夢,可是呢,現實還是打敗了無邪!!面對社會的壓力和殘酷的競爭力自己如何生成下去??我自己對自己說:第一步 先養活自己,才能走好以後的路 開始接觸手機端android那時感覺,做android開發的工資高、android前景廣。可 ...
  • 一,效果圖。 二,工程圖。 三,代碼。 AppDelegate.h AppDelegate.m ...
  • http://mp.weixin.qq.com/s?__biz=MzI5NTAxMzk4OA==&mid=209170198&idx=1&sn=97072f8bb5d7d2434112ae411cdf63df#rd 安裝時 需要輸入密碼 密碼為:www.ifunmac.com ...
  • 本文介紹一下自定義行間距的UILabel的高度如何獲取,需要藉助一下開源的UILabel控制項:TTTAttributedLabel 附下載地址 https://github.com/TTTAttributedLabel/TTTAttributedLabel 下載後,添加到工程裡面,導入頭文件 #im ...
  • 開始運行: 信息輸入: 身份證號查詢: 准考證號查詢: 信息刪除: 輸入錯誤信息: ...
  • 按照我之前安裝5.6的安裝方法(MySQL免安裝版下載與配置)安裝5.7的時候出現問題: mysql服務無法啟動,服務沒有報任何錯誤 其實在這學期開始學習mysql的時候,就聽老師同學說,登錄不了的問題,當時沒有在意,也是因為電腦上早就安裝了mysql5.6,也就沒有在意這個問題。這兩天win10系 ...
  • 本章將講解,Sybase下如何把含逗號字元串轉化為結果集。 示例如下: 把含有逗號的字元串,拆開放入結果集。 當用到臨時表時,可以直接把臨時表當做物理表一樣使用。 over ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...