Using sys.dm_io_virtual_file_stats DMF to get IPOS and BPS

SQL Server keeps track of all the reads and writes it submits to the operating system (OS).  It records this information in sys.dm_io_virtual_file_stats DMF.  We can use the information recorded there in conjunction with the when the SQL was last restarted to figure total number of Input-Output Per Seconds (IOPS) and Bytes Per Second (BPS) generated by SQL Server.

You ask… WHY? Why do I care?

Well let’s say you are having problem with disk sub system, you have multiple databases you are trying to figure out which database generated the most IO?  Or better yet which file did the most work …

You say AHA! I can just select everything virtual file stats DMF.  True, True you can, you can find out which file has the most activity.  But now you go to your SAN guy, you SAN is not good enough for my SQL Server.

SAN guy in return is going to say “Nope, I don’t see any issues…”

So now what?

This is where this information comes useful, you need to present to the SAN guy with total number of IOPS and Throughput per second SQL Server is generating.  Then ask the SAN guy can the current configuration support you IOPS workload?  Can you current HBA configuration or iSCSI configuration support the current workload?

So this is where this script comes in, up_Get_IOPS_n_BPS.  Try it out and tell me what you think, I welcome comments.

SET NOCOUNT ON

DECLARE @SQLRestartDateTime Datetime
DECLARE @TimeInSeconds Float

SELECT @SQLRestartDateTime = create_date FROM sys.databases WHERE database_id = 2

SET @TimeInSeconds = Datediff(s,@SQLRestartDateTime,GetDate())

PRINT 'Input-Output Per Second and Bytes Per Second by Database and File'
PRINT ''

    SELECT   DB_NAME(IVFS.database_id) AS DatabaseName
           , MF.type_desc AS FileType
           , MF.name AS VirtualFileName
           , MF.Physical_Name AS StorageLocation
           , ROUND((num_of_reads + num_of_writes)/@TimeInSeconds,4) AS IOPS
           , ROUND((num_of_bytes_read + num_of_bytes_written)/@TimeInSeconds,2) AS BPS
      FROM sys.dm_io_virtual_file_stats(null,null) IVFS
      JOIN sys.master_files MF ON IVFS.database_id = MF.database_id AND IVFS.file_id = MF.file_id
  ORDER BY DatabaseName ASC, VirtualFileName ASC

  PRINT 'Input-Output Per Second and Bytes Per Second by Database'
  PRINT ''

    SELECT   DB_NAME(IVFS.database_id) AS DatabaseName
           , ROUND((SUM(num_of_reads + num_of_writes))/@TimeInSeconds,4) AS IOPS
           , ROUND((SUM(num_of_bytes_read + num_of_bytes_written))/@TimeInSeconds,2) AS BPS
      FROM sys.dm_io_virtual_file_stats(null,null) IVFS
  GROUP BY db_name(IVFS.database_id)
  ORDER BY DatabaseName ASC

  PRINT 'Total Input-Output Per Second and Bytes Per Second on Server'
  PRINT ''

    SELECT   ROUND((SUM(num_of_reads + num_of_writes))/@TimeInSeconds,4) AS IOPS
           , ROUND((sum(num_of_bytes_read + num_of_bytes_written))/@TimeInSeconds,2) AS BPS
      FROM sys.dm_io_virtual_file_stats(null,null) IVFS

  SET NOCOUNT OFF

I will be adding additional scripts for this that let you calculate IOPS generated in last hour or last day also, maybe the heavy workload happened only recently.  Buttttt… that’s for another day.

Example Output – Input-Output Per Second and Bytes Per Second by Database

Database Name IOPS BPS
AdventureWorks2012 0.0002 8.76
DB1 0.0001 5.15
DB2 0.0001 5.61
BackupDemo 0.0002 7
DBAGoodies 0.0002 6.85
master 0.0003 9.66
model 0.0004 21.05
msdb 0.0002 10.15
tempdb 0.0001 5.52

Example – Total Input-Output Per Seconds and Bytes Per Seconds on Server

IOPS BPS
0.0017 79.75

Update Oct 1, 2012:
Fixed the SQL Statement to get the last restart date. Added “Where database_id = 2”. Since TempDB is recreated every time, we can use that to calculate the our start up time.

11 comments

  1. SELECT @SQLRestartDateTime = create_date FROM sys.databases

    What does this returns .. the last entry of the last created databases….
    how is that good for SQLRestartDateTime?

  2. or you can always get the correct start time for SQL Server by querying sys.dm_os_sys_info DMV for ‘sqlserver_start_time’

    1. Thanks for the tip. Didn’t consider looking in that DMV. I think these values are generally close the time SQL Starts to time TempDB created is usually with in matter of seconds, if these times are too far apart. Then maybe we have issue at SQL Server startup. Thanks again for tip :).

  3. Was looking into setting up perfmon but then this script came handy to get IOPs to date since SQL restart. Ty

  4. I have started a new role and I see that none of the disks for SQL Server tempdb, mdf, ndf and ldf files are on disk which have been formatted as 64k. Will this script help me prove that their performance is suffering because of this? I want to recommend a phased approach of reformatting the drives but I need to have solid evidence.

    Note that this thread suggests it is not as much an issue that I believe but wondering how your code could shed light on this issue. And THANKS for sharing it!!

    64KB disk formatted vs 4KB disk formatted – SQLServerCentral Forums

    1. Hi John,
      The discussion on SQLServerCentral is valid. The performance impact of 64 KB versus 4 KB allocation units is not particularly difficult to demonstrate, and Microsoft has long recommended formatting SQL Server data, log, and TempDB volumes with a 64 KB allocation unit size. The most reliable way to validate any performance impact in a given environment is through controlled testing, typically using disk I/O simulation tools such as SQLIO or similar utilities. [SQL Server…soft Learn | Learn.Microsoft.com], [Storage: P…soft Learn | Learn.Microsoft.com]
      I/O statistics can help indicate whether disks are underperforming, but it’s important to note that 64 KB allocation size is not always the root cause of performance issues. Historically, it was an easy, low-risk optimization that often provided measurable gains on physical servers. In virtualized environments—particularly with VMDK layers and shared storage—it has become much harder to isolate and conclusively prove its impact end to end.
      If we step back and think about what 4 KB versus 64 KB actually means, we’re really talking about the minimum allocation unit on disk. A 4 KB allocation size can reduce wasted space when a volume contains a large number of small files. However, SQL Server data files, log files, and TempDB files are typically large and sequential in nature, so small-file efficiency is rarely a concern. That is why 64 KB has remained the standard recommendation: even a modest performance improvement is still a net win for SQL Server workloads.
      More importantly, disk performance issues can originate from many layers in the stack—poor query patterns, memory pressure, or misconfiguration anywhere along the I/O path (logical disk configuration, VMDK layout, HBA, host, fabric switches, or SAN settings). Any one of these can introduce bottlenecks. In that context, 64 KB formatting has become the “default” optimization because it is simple, low effort, and historically beneficial, not because it is a universal fix.

Leave a reply to Mohit Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.