Sql-Server

使用 sys.dm_os_buffer_descriptors.read_microsec 與 sys.dm_io_virtual_file_stats 計算延遲有什麼區別?

  • September 15, 2022

我正在嘗試計算 SQL 數據庫的磁碟 io 延遲(將頁面從磁碟獲取到記憶體所需的時間)。

以下是我正在探索的兩種方法:

方法 1 - 使用 sys.dm_os_buffer_descriptors :

WITH AggregateBufferPoolUsage AS (
   SELECT
     DB_NAME(database_id) AS [Database Name], 
     CAST(COUNT_BIG(*) * 8/1024.0 AS DECIMAL (15,2)) AS [CachedSize], 
     COUNT(page_id) AS [Page Count], 
     AVG(read_microsec) AS [Avg Read Time (microseconds)] 
   FROM sys.dm_os_buffer_descriptors WITH (NOLOCK) 
   GROUP BY
     DB_NAME(database_id)
)
SELECT
 ROW_NUMBER() OVER(ORDER BY CachedSize DESC) AS [Buffer Pool Rank],
 [Database Name],  
 CAST(CachedSize / SUM(CachedSize) OVER() * 100.0 AS DECIMAL(5,2))
     AS [Buffer Pool Percent], 
 [Page Count],
 CachedSize AS [Cached Size (MB)],
 [Avg Read Time (microseconds)] 
FROM AggregateBufferPoolUsage 
ORDER BY
 [Buffer Pool Rank]
OPTION (RECOMPILE); 

方法 2 - 使用 sys.dm_io_virtual_file_stats:

SELECT 
   [ReadLatency] = 
       CASE WHEN [num_of_reads] = 0 
           THEN 0 ELSE ([io_stall_read_ms] / [num_of_reads]) END, 
   [WriteLatency] = 
       CASE WHEN [num_of_writes] = 0 
           THEN 0 ELSE ([io_stall_write_ms] / [num_of_writes]) END, 
   [Latency] = 
       CASE WHEN ([num_of_reads] = 0 AND [num_of_writes] = 0) 
           THEN 0 ELSE ([io_stall] / ([num_of_reads] + [num_of_writes])) END, 
   [AvgBPerRead] = 
       CASE WHEN [num_of_reads] = 0 
           THEN 0 ELSE ([num_of_bytes_read] / [num_of_reads]) END, 
   [AvgBPerWrite] = 
       CASE WHEN [num_of_writes] = 0 
           THEN 0 ELSE ([num_of_bytes_written] / [num_of_writes]) END, 
   [AvgBPerTransfer] = 
       CASE WHEN ([num_of_reads] = 0 AND [num_of_writes] = 0) 
           THEN 0 ELSE 
               (([num_of_bytes_read] + [num_of_bytes_written]) / 
               ([num_of_reads] + [num_of_writes])) END, 
   LEFT ([mf].[physical_name], 2) AS [Drive], 
   DB_NAME ([vfs].[database_id]) AS [DB], 
   [mf].[physical_name] 
FROM 
   sys.dm_io_virtual_file_stats (NULL,NULL) AS [vfs] 
JOIN sys.master_files AS [mf] 
   ON [vfs].[database_id] = [mf].[database_id] 
   AND [vfs].[file_id] = [mf].[file_id] 
ORDER BY [WriteLatency] DESC; 

對於我正在分析的數據庫,使用方法 1 - avg read_micro 值顯示為 2004 = 0.2ms

使用方法 2 - 平均讀取延遲值(對於數據文件 - .mdf)顯示為 12.3ms

為什麼使用上述方法的延遲計算之間存在如此大的差距/差異?

為什麼使用上述方法的延遲計算之間存在如此大的差距/差異?

sys.dm_os_buffer_descriptors包括讀取時間為 0 的新 BUF,因為它們是來自記憶體的新 BUF,不必從磁碟讀取。相反,sys.dm_io_virtual_files_stats包括文件上的讀取活動,這些活動可能不僅僅用於 BUF。

如果你創建一個新的 BUF 因為你正在格式化一個新頁面,它不會磁碟讀取,它只在記憶體中(除了日誌條目)並且在檢查點或惰性寫入器之前不會刷新到磁碟。將沒有讀取時間,因為它從未從磁碟讀取。現在您查詢這個 DMV,它顯示這個 BUF 的值為 0 並對其進行平均,這會降低整體平均值。

sys.dm_os_buffer_descriptors顯示緩衝池中每個頁面的最後一次讀取時的資訊。您正在為仍在緩衝池中的頁面取平均每頁,不在緩衝池中的頁面將不會顯示。

sys.dm_io_virtual_file_stats以每個文件為基礎顯示自伺服器啟動以來該文件的讀取時間。這可能包括多次讀取相同的頁面,並且可能包括不再在緩衝池中(或此後再次讀取)的數據的長時間停頓。

引用自:https://dba.stackexchange.com/questions/316882