想了很久索引的重要性應該怎麼寫?講原理結構?我估計大部分人不肯意看,也不肯意花那麼多時間仔細研究。光寫應用?感受不明白原理同樣不會用。舉例說明?狀況太多也寫不全....到底該怎麼寫呢?html
隨便寫吧,想到哪寫到哪!sql
前面不少篇無論CPU、內存、磁盤、語句等等等都提到了索引的重要,我想剛剛開始學數據庫的在校學生都知道索引對語句性能的重要性。但他們可能不知道,對語句的重要性就是對系統的重要性!數據庫
拋出一個問題 :你相信一條語句就能讓你的大系統掛掉麼?緩存
帶着問題,首先仍是貼出個人座駕工具
最近不太喜歡紅色換了一輛!oop
--------------博客地址---------------------------------------------------------------------------------------sqlserver
Expert 診斷優化系列 http://www.cnblogs.com/double-K/post
廢話很少說,直接開整-----------------------------------------------------------------------------------------性能
下面這樣一個小SQL 你該怎麼樣添加最優索引學習
兩個表上如今只有彙集索引
bigproduct 表上已經有彙集索引 ProductID
bigtransactionhistory 表上已經有彙集索引 TransactionID
select p.productnumber,p.reorderpoint,th.Quantity from bigproduct as p join bigtransactionhistory as th on th.productid=p.productid and th.TransactionDate > p.SellStartDate where p.name in ('LL Crankarm1000','ML Crankarm1000') and th.TransactionDate > '2010-01-01'
你是否一眼就能看出來呢?
答案將在文章中逐步揭曉~~~
看過我前面文章的看官們必定會發現我很喜歡用「簡單粗暴」這個詞,一是由於詞彙量小文筆也差,真心用不出高大上的詞兒! 再一個,大家不喜歡簡單粗暴麼~~乾貨最重要,不是麼?
首先咱們看一下沒有優化前的執行計劃
clustered index scan 這其實就是表掃描,不是table scan 只是由於表上有彙集索引
能夠看出這個查詢倆表都使用了表掃描!
where 條件添加索引
首先大多數人都知道 where 條件中的字段須要添加索引! 咱們添加一下看看效果建立
在 bigproduct 表上建立 name 列索引 ,在bigtransactionhistory表上建立 TransactionDate 列索引。
再次執行語句看一下效果!
添加where索引之後能夠看到如下幾個現象
解釋一下出現的現象 : 首先一點bigproduct 邊添加的where 條件索引,起到了做用,執行的時候不是全表掃描了,邏輯讀有明顯的降低,出現的 KEY Lookup 是由於選擇(select)的列,在索引中沒有,而須要經過彙集索引再查找一次,再找一次也意味着多一部分開銷!
那麼一樣添加了where 條件索引的bigtransactionhistory 表爲何沒起做用呢? 那是由於SQL優化器在選擇計劃的時候認爲,不使用TransactionDate 列索引查找效率會更好!
真的麼? 咱們來驗證一下,經過指定選擇索引,來讓優化器選擇索引查找!
強制使用索引之後,能夠看出邏輯讀由 14W 變成1961W,語句時間也變得很長,這就是優化器爲何不選用你加的索引!優化器仍是很智能的吧。
高能預警:優化器可不是何時都這麼智能的...因爲緩存計劃或優化器抽風等緣由,也會出現優化器用了這種索引,致使你的語句奇慢,讀飆升直接影響到你的內存、磁盤、CPU資源!另外若是這樣一條語句是系統中一條很頻繁運行的語句,你的系統就掛了!沒錯就掛了!這就是開篇拋出的問題就是由於一條語句!
消滅Key Lookup 添加select 字段
這就是傳說中的覆蓋索引!
看到執行計劃中存在Key Lookup 並且消耗佔比很高,如上面強制索引的計劃,那麼咱們就要想到的 在索引中包含那些SELECT 的列!若是消耗低,邏輯讀少,如上面bigproduct 表中的Key Lookup 就能夠忽略(若是你追求完美,也同樣優化就能夠了)。
包含列的圖形化建立 : @秋仙 特地給你的說明
語句建立就是 :
CREATE NONCLUSTERED INDEX TransactionDate包含ProductID_Quantity ON [dbo].[bigTransactionHistory] ([TransactionDate]) ------INCLUDE 就是包含列 INCLUDE ([ProductID],[Quantity]) GO
下面咱們添加一下看看效果 :
添加select 索引字段後能夠看出的現象:
經過優化索引添加select 字段,咱們看出語句又一次獲得了提高 bigtransactionhistory 從表掃描變成索引查找,邏輯讀由14W變成 1W!這是一個質的飛躍啊!
CREATE NONCLUSTERED INDEX TransactionDate包含ProductID_Quantity
ON [dbo].[bigTransactionHistory] ([TransactionDate]) ------INCLUDE 就是包含列 INCLUDE ([ProductID],[Quantity]) GO
那爲何還提示缺乏索引呢? 建立一下試試吧!
索引再優化加入表關聯列
按照提示咱們建立索引 : 和上一個索引的不一樣 ProductID 列由包含列變成了索引列!
USE [AdventureWorks2012] GO CREATE NONCLUSTERED INDEX ProductID_TransactionDate包含Quantity ON [dbo].[bigTransactionHistory] ([ProductID],[TransactionDate]) INCLUDE ([Quantity])
咱們看一下效果:
再次優化索引之後能夠看到如下幾個現象
又一次質的飛躍!讀從原來的14W 變成1W 又變成18,這樣大大減小了內存和IO的消耗,另外並行計劃也變成了串行,無疑又減小了大量CPU的消耗!語句時間,我想這裏就不用多說了吧?
高能預警:這裏所說的hash join,並行變串行,不懂的朋友能夠在百度自行學習,這裏只是針對當前語句的狀況,不能一律而論!
精簡你的索引
你們都知道,索引會致使update、insert、delete操做變慢!那麼儘可能精簡你的索引就是一個很重要的話題了!
上面的優化過程當中咱們建立了幾個索引,以bigTransactionHistory爲例來看一下:
腳本這裏就不貼了,其實咱們最後建立的索引 ProductID_TransactionDate包含Quantity 已經包含了前兩個索引,並且能夠說不管任何相似語句都使用ProductID_TransactionDate包含Quantity 就能夠了!
那麼咱們就能夠清除前兩個索引!
--------------博客地址---------------------------------------------------------------------------------------
Expert 診斷優化系列 http://www.cnblogs.com/double-K/
-----------------------------------------------------------------------------------------------------
至此語句的優化算是結束了,留下的就是bigproduct 依然有一個Key Lookup能夠優化,能夠仿照上面的繼續優化,這裏就不細說了。語句只是通過了簡單的索引優化就從一輛2手QQ變成了法拉利,是否是很神奇?
這就是索引的重要性!
開篇小測試你作對了麼?若是沒作對那麼這麼請你自行模擬一個場景再現本篇的話題吧!
-----------------------------------------------------------------------------------------------------
總結 : 每每一個系統的總體緩慢都是由於索引問題致使的,優化索引是對你係統最簡單的保養!
不要小看一條語句的威力,一條語句足可讓你的系統完全沒法工做!
一個問題隨之而來語句一條一條漫無目的的優化麼?我怎麼找出系統的問題語句?怎麼樣的一個優先級?
請參見前文 : Expert 診斷優化系列------------------語句調優三板斧
後一篇我將使用 Expert for sqlserver 工具講述怎麼樣針對重點語句調索引,喜歡的看官請mark了!
----------------------------------------------------------------------------------------------------
注:此文章爲原創,歡迎轉載,請在文章頁面明顯位置給出此文連接!
若您以爲這篇文章還不錯請點擊下右下角的推薦,很是感謝!
引用高大俠的一句話 :「拒絕SQL Server背鍋,從我作起!」
爲了方便閱讀給出系列文章的導讀連接:
----------------------深刻索引原理推薦博客--------------------------
目測這幾篇文章每篇的編寫時間都要超過10小時,很是值得閱讀!
pursuer.chen 的博客
樺仔的博客