1. 程式人生 > 資料庫 >sql server效能調優 I/O開銷的深入解析

sql server效能調優 I/O開銷的深入解析

一.概述

IO 記憶體是sql server最重要的資源,資料從磁碟載入到記憶體,再從記憶體中快取,輸出到應用端,在sql server 記憶體初探中有介紹。在明白了sqlserver記憶體原理後,就能更好的分析I/O開銷,從而提升資料庫的整體效能。 在生產環境下資料庫的sqlserver服務啟動後一個星期,就可以通過dmv來分析優化。在I/O分析這塊可以從物理I/O和記憶體I/O二方面來分析, 重點分析應在記憶體I/O上,可能從多個維度來分析,比如從sql server服務啟動以來 歷史I/O開銷總量分析,自執行計劃編譯以來執行次數總量分析,平均I/0次數分析等。

sys.dm_exec_query_stats:返回快取的查詢計劃,快取計劃中的每個查詢語句在該檢視中對應一行。當sql server工作負載過重時,該dmv也有可以統計不正確。如果sql server服務重啟快取的資料將會清掉。這個dmv包括了太多的資訊像記憶體掃描數,記憶體空間數,cpu耗時等,具體檢視msdn文件。

sys.dm_exec_sql_text:返回的 SQL 文字批處理,它是由指定sql_handle,其中的text列是查詢的文字。

1.1 按照物理讀的頁面數排序 前50名

SELECT TOP 50
 qs.total_physical_reads,qs.execution_count,qs.total_physical_reads/qs.execution_count AS [avg I/O],qs. creation_time,qs.max_elapsed_time,qs.min_elapsed_time,SUBSTRING(qt.text,qs.statement_start_offset/2,(CASE WHEN qs.statement_end_offset=-1
 THEN LEN(CONVERT(NVARCHAR(max),qt.text))*2
 ELSE qs.statement_end_offset END -qs.statement_start_offset)/2) AS query_text,qt.dbid,dbname=DB_NAME(qt.dbid),qt.objectid,qs.sql_handle,qs.plan_handle
 from sys.dm_exec_query_stats qs
 CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
 ORDER BY qs.total_physical_reads DESC

如下圖所示:

  total_physical_reads:計劃自編譯後在執行期間所執行的物理讀取總次數。

  execution_count :計劃自上次編譯以來所執行的次數。

  [avg I/O]: 平均讀取的物理次數(頁數)。

  creation_time:編譯計劃的時間。

query_text:執行計劃對應的sql指令碼

後面來包括所在的資料庫ID:dbid,資料庫名稱:dbname

1.2 按照邏輯讀的頁面數排序 前50名

SELECT TOP 50
 qs.total_logical_reads,qs.total_logical_reads/qs.execution_count AS [AVG IO],(CASE WHEN qs.statement_end_offset=-1 
 THEN LEN(CONVERT(NVARCHAR(max),qt.text)) *2
 ELSE qs.statement_end_offset END -qs.statement_start_offset)/2) 
 AS query_text,creation_time,qs.plan_handle
 from sys.dm_exec_query_stats qs
 CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
 ORDER BY qs.total_logical_reads DESC

如下圖所示:

通過上面的邏輯記憶體截圖來簡要分析下:

  從記憶體掃描總量上看最多的是8311268次頁掃描,自執行編譯後執行t-sql指令碼358次,這裡的耗時是毫秒為單位包括最大耗時和最小耗時,平均I/O是232115次(頁),該語句文字是一個update 修改,該表資料量大沒有完全走索引(權衡後不對該語句做索引覆蓋),但執行次數少,且每次執行時間是非工作時間,雖然掃描開銷大,但沒有影響白天客戶使用。

  從執行次數是有一個43188次, 記憶體掃描總量排名39位。該語句雖然只有815條,但執行次數很多,如裡伺服器有壓力可以優化,一般是該語句沒有走索引。把文字拿出來如下

SELECT Count(*) AS TotalCount FROM [MEM_FlagshipApply]
 WITH(NOLOCK) Where (((([Status] = 2) AND ([IsDeleted] = 1)) AND ([MemType] = 0)) AND ([MEMID] <> 6))

下面兩圖一個是分析該語句的執行計劃,sqlserver提示缺少索引,另一個是i/o統計掃描了80次。

新建索引後在來看看

 CREATE NONCLUSTERED INDEX ix_1
ON [dbo].[MEM_FlagshipApply] ([Status],[IsDeleted],[MemType],[MEMID])

  

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。