舒適提示:本篇內容均來自網上,本人只作了稍微處理,未進行細緻研究,僅當作之後不備之需,如若你喜歡可盡情轉走。 數據庫
不少數據庫系統性能不理想是由於系統沒有通過總體優化,存在大量性能低下的SQL 語句。這類SQL語句性能很差的首要緣由是缺少高效的索引。沒有索引除了致使語句自己運行速度慢外,更是致使大量的磁盤讀寫操做,使得整個系統性能都受之影響而變差。 ide
解決這類系統的首要辦法是優化這些沒有索引或索引不夠好的SQL語句。 性能
1、建立索引的關鍵 大數據
優化SQL語句的關鍵是儘量減小語句的logical reads。這裏說的logical reads是指語句執行時須要訪問的單位爲8K的數據頁總數。logical reads 越少,其須要的內存和CPU時間也就越少,語句執行速度就越快。不言而喻,索引的最大好處是它能夠極大減小SQL語句的logical reads數目,從而極大減小語句的執行時間。 優化
建立索引的關鍵是索引要可以大大減小語句的logical reads。一個索引好很差,主要看它減小的logical reads多很少。 .net
運行set statistics io命令能夠獲得SQL語句的logical reads信息。 排序
set statistics io on 索引
select au_id,au_lname ,au_fname 事務
from pubs..authors where au_lname ='Green' 內存
set statistics io on
若是Logical reads很大,而返回的行數不多,也即二者相差較大,那麼每每意味者語句須要優化。Logical reads中包含該語句從內存數據緩衝區中訪問的頁數和從物理磁盤讀取的頁數。而physical reads表示那些沒有駐留在內存緩衝區中須要從磁盤讀取的數據頁。Read-ahead reads是SQL Server爲了提升性能而產生的預讀。預讀可能會多讀取一些數據。
優化的時候咱們主要關注Logical Reads就能夠了。
注意若是physical Reads或Read-ahead reads很大,那麼每每意味着語句的執行時間(duration)裏面會有一部分耗費在等待物理磁盤IO上。
2、單字段索引,組合索引和覆蓋索引
單字段索引是指只有一個字段的索引,而組合索引指有多個字段構成的索引。
1. 對出如今where子句中的字段加索引
set statistics profile on
set statistics io on
go
select .... from tb where ...
go
set statistics profile off
set statistics io off
set statistics profile命令將輸出語句的執行計劃。也許你會問,爲何不用SET SHOWPLAN_ALL呢?使用SET SHOWPLAN_ALL也是能夠的。不過set statistics profile輸出的是SQL 語句的運行時候真正使用的執行計劃,而SET SHOWPLAN_ALL輸出的是預計(Estimate)的執行計劃。使用SET SHOWPLAN_ALL是後面的語句並不會真正運行。
用了Table Scan,也就是對整個表進行了全表掃描。全表掃描的性能一般是不好的,要儘可能避免。
若是上面的select語句是數據庫系統常常運行的關鍵語句, 那麼應該對它建立相應的索引。建立索引的技巧之一是對常常出如今where條件中的字段建立索引,Table Scan也變成了Index Seek,性能極大提升設法避免Table scan或Index scan是優化SQL 語句使用的經常使用技巧。一般Index Seek須要的logical reads比前二者要少得多。
2.組合索引
若是where語句中有多個字段,那麼能夠考慮建立組合索引。組合索引中字段的順序是很是重要的,越是惟一的字段越是要靠前。另外,不管是組合索引仍是單個列的索引,儘可能不要選擇那些惟一性很低的字段。
好比說,在只有兩個值0和1的字段上創建索引沒有多大意義。因此若是對單字段進行索引,建議使用set statistics profile來驗證索引確實被充分使用。logical reads越少的索引越好。
3.覆蓋索引
覆蓋索引可以使得語句不須要訪問表僅僅訪問索引就可以獲得全部須要的數據。由於彙集索引葉子節點就是數據因此無所謂覆蓋與否,因此覆蓋索引主要是針對非彙集索引而言。
執行計劃中除了index seek外,還有一個Bookmark Lookup關鍵字。Bookmark Lookup表示語句在訪問索引後還須要對錶進行額外的Bookmark Lookup操做才能獲得數據。
也就是說爲獲得一行數據起碼有兩次IO,一次訪問索引,一次訪問基本表。
若是語句返回的行數不少,那麼Bookmark Lookup操做的開銷是很大的。覆蓋索引可以避免昂貴的Bookmark Lookup操做,減小IO的次數,提升語句的性能。覆蓋索引須要包含select子句和WHERE子句中出現的全部字段。Where語句中的字段在前面,select中的在後面。
logical reads,是大大減小了。Bookmark Lookup操做也消失了。因此建立覆蓋索引是減小logical reads提高語句性能的很是有用的優化技巧。
實際上索引的建立原則是比較複雜的。有時候你沒法在索引中包含了Where子句中全部的字段。在考慮索引是否應該包含一個字段時,應考慮該字段在語句中的做用。
好比說若是常常以某個字段做爲where條件做精確匹配返回不多的行,那麼就絕對值得爲這個字段創建索引。
再好比說,對那些很是惟一的字段如主鍵和外鍵,常常出如今group by,order by中的字段等等都值得建立索引。
問題1,是否值得在identity字段上創建彙集索引。
答案取決於identity 字段如何在語句中使用。若是你常常根據該字段搜索返回不多的行,那麼在其上創建索引是值得的。反之若是identity字段根本不多在語句中使用,那麼就不該該對其創建任何索引。
問題2,一個表應該創建多少索引合適。
若是表的80%以上的語句都是讀操做,那麼索引能夠多些。可是不要太多。特別是不要對那些更新頻繁的表其創建不少的索引。不多表有超過5個以上的索引。過多的索引不但增長其佔用的磁盤空間,也增長了SQL Server 維護索引的開銷。
問題3:爲何SQL Server在執行計劃中沒有使用你認爲應該使用的索引?緣由是多樣的。
一種緣由是該語句返回的結果超過了表的20%數據,使得SQL Server 認爲scan比seek更有效。另外一種緣由多是表字段的statistics過時了,不能準確反映數據的分佈狀況。你可使用命令UPDATE STATISTICS tablename with FULLSCAN來更新它。
只有同步的準確的statistics才能保證SQL Server 產生正確的執行計劃。過期的老的statistics常會致使SQL Server生成不夠優化的甚至愚蠢的執行計劃。
因此若是你的表頻繁更新,而你又以爲和之相關的SQL語句運行緩慢,不妨試試UPDATE STATISTIC with FULLSCAN 語句。
問題四、什麼使用匯集索引,何時使用非彙集索引
在SQL Server 中索引有彙集索引和非彙集索引兩種。它們的主要差異是前者的索引葉子就是數據自己,然後者的葉子節點包含的是指向數據的書籤(即數據行號或彙集索引的key)。
對一個表而言彙集索引只能有一個,而非彙集索引能夠有多個。
只是彙集索引沒有Bookmark Lookup操做。
何時應該使用匯集索引? 何時使用非彙集索引? 取決於應用程序的訪問模式。
個人建議是在那些關鍵的字段上使用匯集索引。一個表通常都須要創建一個彙集索引。
對於何時使用匯集索引,SQL Server 2000聯機手冊中有以下描述:
在建立彙集索引以前,應先了解您的數據是如何被訪問的。可考慮將彙集索引用於:
包含大量非重複值的列。
使用下列運算符返回一個範圍值的查詢:BETWEEN、>、>=、< 和 <=。
被連續訪問的列。
返回大型結果集的查詢。
常常被使用聯接或 GROUP BY 子句的查詢訪問的列;通常來講,這些是外鍵列。
對 ORDER BY 或 GROUP BY 子句中指定的列進行索引,可使 SQL Server 沒必要對數據進行排序,由於這些行已經排序。這樣能夠提升查詢性能。
OLTP 類型的應用程序,這些程序要求進行很是快速的單行查找(通常經過主鍵)。應在主鍵上建立彙集索引。
彙集索引不適用於:
頻繁更改的列
這將致使整行移動(由於 SQL Server 必須按物理順序保留行中的數據值)。這一點要特別注意,由於在大數據量事務處理系統中數據是易失的。
寬鍵
來自彙集索引的鍵值由全部非彙集索引做爲查找鍵使用,所以存儲在每一個非彙集索引的葉條目內。
總結:
如何使一個性能緩慢的系統運行更快更高效,不但須要總體分析數據庫系統,找出系統的性能瓶頸,更須要優化數據庫系統發出的SQL 語句。
一旦找出關鍵的SQL 語句並加與優化,性能問題就會迎刃而解。