讀書摘要:
1、Begin Tran
delete from production.ProductCosthistory
該查詢返回受影響的記錄數。注意該查詢故意沒有提交,也就是說,其中包含Begin Tran命令,但沒有Rollback和Commit命令。由於沒有後面的命令,該表當前處於鎖定狀態。通常,用戶可能運行沒有begin tran的查詢。在這些情況下,實際上它是一個隱式事務,且該事務在批處理完成時立即提交。
接下來,在不關閉前一個窗口的情況下,打開一個新的查詢窗口,並在AdventureWorks數據庫中運行如下查詢。
Select * from Production.ProductCostHistory
該查詢永遠不會返回結果,且將處於掛起狀態。注意在每個查詢窗口的地步顯示了登錄名,並在括號中顯示進程ID,在保持查詢窗口打開的同時打開“活動監視器”,查看這些鏈接當前的狀態。
用戶可通過添加With (nolock)字句,請求對未提交數據的髒讀。
select * from production.ProductCosthistory
with (nolock)
2、在T-SQL中監視進程
sp_who和sp_who2與“活動監視器”非常類似。
3、sys.dm_exec_connections
4、DBCC INPUTBUFFER
讓用戶能夠查看各個進程ID在運行哪些SQL命令。該命令只接受一個輸入參數,即要對其進行診斷的連接的進程ID。
5、Sys.dm_exec_sql_text
有些時候可能需要表格格式的DBCC INPUTBUFFER結果。可使用動態管理函數sys.dm_exec_sql_text來獲得特定查詢的文本。他可以與sqy.dm_exec_query_stats動態管理視圖結合使用,以獲得所有數據庫中性能最差的查詢。
在設計select語句時,應該注意以下幾種影響查詢效率的情況。
(1)沒有創建索引,或者沒有正確地使用索引。這是最有可能影響數據庫查詢的原因之一。創建索引是優化數據查詢效率的重要手段。
(2)存在死鎖的情況,從而導致select語句掛起,無法返回結果集。
(3)返回了不必要的列。很多程序員喜歡使用select * fromtablename 來查詢表或視圖中的數據,*代表或視圖中的所有字段。如果表或視圖的數據裏比較大,則查詢所有字段會浪費更多的系統資源,從而影響查詢效率。建議用戶在使用select語句時,只返回必要的列。
(4)在SELECT語句中使用WHERE子句,設置查詢條件,只返回必要的記錄。
(5)使用在SELECT語句中使用TOP關鍵字,限制返回的記錄數量。
(6)如果在WHERE子旬中使用LIKE謂詞進行模糊查詢,則要注意通配符的使用方法。
(7)慎用UNION關鍵字,因爲它會影響查詢的效率。
(8)慎用DISTINCT關鍵字,因爲在結果集中返回重複的記錄並不會影響查詢的效率。相反,過濾掉重複的記錄會浪費查詢的時間和系統資源。因此,除非必須如此,不要使用DISTINCT關鍵字。
(9)如果需要經常對錶中的數據進行統計,可以在表中增加一個統計字段,每次表中數據發生變化時,動態更新統計字段。這樣,在查詢統計結果時,就不需要臨時對錶中的數據統計計算了。
(10)如果需要多次對一個數據量非常大的表中的一部分數據進行查詢操作,可以將這部分數據保存到臨時表中,然後對臨時表進行查詢操作。如果需要,可以在臨時表上創建索引。
(11)在WHERE子旬中,有時使用BETWEEN關鍵字比使用IN關鍵字要快,因爲IN關鍵字對其後面的集合中的每個元素都進行比較操作。如果必須使用IN關鍵宇,則可將頻繁使用的值放在集合的前面,從而減少比較的次數。
(12)儘量少使用視圖,特別是嵌套視圖,可以直接從表中獲取數據。在開發應用程序時,有時程序員爲了方便,設計一個包含很多字段的大視圖,無論需要什麼數據,都可以通過查詢此視圖獲取到。實際上,最好從表中直接獲取數據,以避免查詢大視圖而造成的系統開銷。建議使用存儲過程代替視圖,從而提高執行的效率。
(13)如果不需要對結果集進行排序,則不使用ORDERBY子句,因爲排序操作會佔用系統資源。
(14)不要在WHERE子句中“=”的左側使用函數和表達式,因爲系統將無法應用函數或表達式中的索引。
(15)當判斷表中是否包含記錄時,使用EXISTS關鍵字,而不要使用COUNT統計表中所有的記錄數量。
Physical Disk包含的主要計數器
計數器 | 說明 |
%Disk Read Time | 所選磁盤驅動器爲讀請求提供服務所用時間的百分比 |
%Disk Time | 所選磁盤驅動器爲讀或寫入請求提供服務所用時間的百分比 |
%Disk Write Time | 所選磁盤驅動器爲寫請求提供服務所用時間的百分比 |
%Idle Time | 在實例間隔時磁盤閒置時間的百分比 |
Avg.Disk Bytes/Read | 在讀取操作時從磁盤上傳送的字節平均數 |
Avg.Disk Bytes/Transfer | 在寫入或讀取操作時從磁盤上傳送或傳出字節的平均數 |
Avg.Disk Bytes/Write | 在寫入操作時從磁盤上傳送的字節平均數 |
Avg.Disk Queue Length | 讀取和寫入請求的平均數 |
Avg.Disk Read Queue Length | 讀取請求的平均數 |
Avg.Disk sec/Read | 以秒計算的在磁盤上讀取數據的所需平均時間 |
Avg.Disk sec/Tranfer | 以秒計算的在磁盤傳送所需平均時間 |
Avg.Disk sec/Write | 以秒計算的在此盤上寫入數據的所需平均時間 |
Avg.Disk Write Queue Length | 寫入請求的平均數 |
Current Disk Queue Length | 在收集性能數據時磁盤上當前的請求數量。爲了提高性能,此差應該平均小於2 |
Disk Bytes/sec | 在進行寫入或讀取操作時從磁盤上傳送或傳出的字節速率 |
Disk Read Bytes/sec | 在讀取操作時從磁盤上傳字節的速率 |
Disk Read/sec | 在此盤上讀取操作的速率 |
Disk Transfer/sec | 在磁盤上讀取/寫入操作速率 |
Disk Write Bytes/sec | 在寫入操作時傳送到磁盤上的字節速度 |
Disk Writes/sec | 在磁盤上寫入操作的速率 |
可以使用Current Disk Queue length 和 %Disk Time計數器的值檢測磁盤子系統中的瓶頸。如果這兩個計數器的值一直很高,則可以考慮更換速度更快的磁盤或將數據庫文件移動到其他物理硬盤上。
計數器 | 說明 |
Buffer cache hit ratio | 可在緩衝池中找到兒不必要從磁盤讀取的頁所佔的百分比 |
checkpoint pages/sec | 檢查點或其他要求刷新全部髒頁的操作所刷新的頁數 |
databse pages | 緩衝池中有數據庫內容的頁數 |
Free list stalls/sec | 必須等待可用頁的請求數 |
Free pages | 所有可用列表的總頁數 |
Lazy writes/sec | 緩衝區管理器的惰性編寫器寫入的緩衝區數 |
Page life expectancy | 沒有引用的頁停留在緩衝池中的時間(秒) |
Page lookups/sec | 要求在緩衝池中查找頁的請求數 |
Page reads/sec | 執行的物理數據庫頁讀取數 |
Page reads/sec | 執行的物理數據庫頁寫入數 |
Page writes/sec | 緩衝池中的理想的頁數 |
Total pages | 緩衝池中的頁數,包括數據庫頁,可用頁和被盜頁 |
通常可以監測Page reads/sec和Page writes/sec這兩個計數器,如果它們的值比較高,則需要調整應用程序或數據庫以較少I/O操作。增加硬件的I/O容量或添加內存
SQL Server設置的情況下,SQL server中的性能殺手按照粗略的順序(最糟糕的首先出現)排列如下:
1、低質量的索引
2、不精確的統計
3、過多的阻塞和死鎖
4、不基於數據集的操作,通常是T-sql遊標;
5、低質量的查詢設計
6、低質量的數據庫設計
7、過多的碎片
8、不可重用的執行計劃
9、低質量的執行計劃,通常是因爲參數嗅探(parameter sniffing)所導致的
10、執行計劃頻繁重編譯
11、遊標的錯誤使用
12、數據庫日誌的錯誤配置
13、過多使用或者錯誤配置tempdb