http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能優化之索引篇html
近期項目須要, 作了一段時間的SQL Server性能優化,遇到了一些問題,也積累了一些經驗,現總結一下,與君共享。SQL Server性能優化涉及到許多方面,如良好的系統和數據庫設計,優質的SQL編寫,合適的數據表索引設計,甚至各類硬件因素:網絡性能、服務器的性能、 操做系統的性能,甚至網卡、交換機等。這篇文章主要講到如何改善索引,還將有另外一篇討論如何改善SQL語句。
首先須要強調一下,水能載舟,亦能覆舟。創建「適當」的索引是實現查詢優化的首要前提。
當根據索引碼的值搜索數據時,索引提供了對數據的快速訪問。事實上,沒有索引,數據庫也能根據SELECT語句成功地檢索到結果,但隨着表變得越 來越大,使用「適當」的索引的效果就愈來愈明顯。索引有助於提升檢索性能,但過多或不當的索引也會致使系統低效。由於用戶在表中每加進一個索引,數據庫就 要作更多的工做。過多的索引甚至會致使索引碎片。因此,要創建一個「適當」的索引體系,特別是對聚合索引的建立,更應精益求精,以使數據庫能獲得高性能的 發揮。
簡述SQL Server的索引
SQL Server提供了兩種索引:彙集索引(clustered index,也稱聚類索引、簇集索引)和非彙集索引(nonclustered index,也稱非聚類索引、非簇集索引)。
彙集索引肯定表中數據的物理順序。彙集索引相似於電話簿,後者按姓氏排列數據。因爲彙集索引規定數據在表中的物理存儲順序,所以一個表只能包含一個彙集索引。但該索引能夠包含多個列(組合索引),就像電話簿按姓氏和名字進行組織同樣。
彙集索引對於那些常常要搜索範圍值的列特別有效。使用匯集索引找到包含第一個值的行後,即可以確保包含後續索引值的行在物理相鄰。例如,若是應用 程序執行的一個查詢常常檢索某一日期範圍內的記錄,則使用匯集索引能夠迅速找到包含開始日期的行,而後檢索表中全部相鄰的行,直到到達結束日期。這樣有助 於提升此類查詢的性能。一樣,若是對從表中檢索的數據進行排序時常常要用到某一列,則能夠將該表在該列上彙集(物理排序),避免每次查詢該列時都進行排 序,從而節省成本。
非彙集索引與課本中的索引相似。數據存儲在一個地方,索引存儲在另外一個地方,索引帶有指針指向數據的存儲位置。索引中的項目按索引鍵值的順序存 儲,而表中的信息按另外一種順序存儲(這能夠由彙集索引規定)。若是在表中未建立彙集索引,則沒法保證這些行具備任何特定的順序。
更詳細的介紹請參考MSDN上關於索引的介紹。http://msdn.microsoft.com/zh-cn/library/ms189271.aspx java
使用SQL Server的索引
問題又來了,既然分了兩種索引,什麼時候何種狀況用何種索引?那就看看下錶吧。簡單的說就是:對於小數目的不一樣值,或列常常被分組排序,或須要返回某範圍內的數據時使用匯集索引;對於大數目的不一樣值,或列常常被分組排序,或列被頻繁更新時使用非彙集索引。
數據庫
|
使用匯集索引性能優化 |
使用非彙集索引服務器 |
列常常被分組排序網絡 |
應數據庫設計 |
應性能 |
返回某範圍內的數據優化 |
應spa |
不該 |
一個或極少不一樣值 |
不該 |
不該 |
小數目的不一樣值 |
應 |
不該 |
大數目的不一樣值 |
不該 |
應 |
頻繁更新的列 |
不該 |
應 |
外鍵列 |
應 |
應 |
主鍵列 |
應 |
應 |
頻繁修改索引列 |
不該 |
應 |
如何改善索引的一些經驗:
1. 索引首先要知足你的應用中最關鍵或者是被不少用戶頻繁執行的查詢。
若某個查詢每個月僅執行一次,要考慮是否值得爲其涉及表建立了索引。要知道在當月的其它時間數據庫系統對該索引的維護開銷是要超過知足該查詢的表掃描的開銷的。因此,好鋼用在刀刃上,好索引用在關鍵頻繁的查詢上。
2. 在常常進行鏈接,可是沒有指定爲外鍵的列上創建索引。
在嵌套查詢中,對錶的順序存取對查詢效率可能產生致命的影響。好比採用順序存取策略,一個嵌套3層的查詢,若是每層都查詢 1000行,那麼這個查詢就要查詢10億行數據。避免這種狀況的主要方法就是對鏈接的列進行索引。例以下面的一條SQL,鏈接這兩個表:tblA(id, c1, c2, …)和tblB(id, …),就須要分別在兩個表的id字段上創建索引。
其中Clustered Index Scan的執行計劃
其中Clustered Index Seek的執行計劃
如此可見造成索引覆蓋的必要性。
6. 非彙集索引與精確查找的默契
對於某個表中的某個字段存在大數目的不一樣值時,爲該字段建個非彙集索引會達到意想不到的效果。由於數據庫系統在搜索數據值時,先對非彙集索引進行 搜索,找到數據值在表中的位置,而後從該位置直接檢索數據。由於索引包含描述查詢所搜索的數據值在表中的精確位置的條目,這也是爲何非彙集索引是精確匹 配查詢的最佳方法。例如,在employee表爲emp_id列建了非彙集索引,要搜索其僱員ID (emp_id) > 1000的全部人,SQL Server會在索引中直接跳到emp_id = 1000這樣一個條目以後,列出匹配的emp_id列在表中的頁和行,而後直接轉到該頁該行。
7. 若是你是皮爾斯,SQL Server 的執行計劃就是朗多
SQL Server 2005的Microsoft SQL Server Management Studio和Database Engine Tuning Advisor(DETA)是很是好的性能調試助手,可使用它們對SQL語句調優,查看估計的執行計劃開銷,用DETA生成優化建議,採納或參考索引優 化部分。
須要注意的是,對於估計的執行計劃,不要過於關注裏面顯示的開銷比例,而實際上這個有時會誤導。我在實際優化過程當中就被發現,一個index scan的執行項開銷只佔25%,另外一個鍵查找的開銷佔50%,而鍵查找部分根本沒有可優化的,SEEK謂詞就是ID=XXX這個創建在主鍵上的查找。而 仔細分析能夠看到,後者CPU開銷0.00015,I/O開銷0.0013。而前者呢,CPU開銷1.4xxxx,I/O開銷也遠大於後者。所以,優化重 點應該放在前者。
網上這類的文章不少,這裏就不作贅述了。能夠參考一篇較早的文章:SQL Server性能調優入門(圖文版)
另外還有一篇不錯的文章,共享在這裏:探討如何在有着1000萬條數據的MS SQL SERVER數據庫中實現快速的數據提取和數據分頁