SQL Server 2016 Database Specific Query

Daniel AG by Daniel AG

Query 1

 

Individual File Sizes and space available for current database(File Sizes and Space)


SELECT f.NAME                                     AS [file name], 

       f.physical_nameas                          [physical name], 

       Cast(( f.size / 128.0 ) AS DECIMAL(15, 2)) AS [total size in mb], 

       Cast(f.size / 128.0 - Cast(Fileproperty(f.NAME, 'spaceused') AS INT) / 

                             128.0 AS 

            DECIMAL(15, 2))                       AS [available space in mb], 

       f.[file_id], 

       fg.NAME                                    AS [filegroup name], 

       f.is_percent_growth, 

       f.growth, 

       fg.is_default, 

       fg.is_read_only, 

       fg.is_autogrow_all_files 

FROM   sys.database_files AS f WITH (nolock) 

       LEFT OUTER JOIN sys.filegroups AS fg WITH (nolock) 

                    ON f.data_space_id = fg.data_space_id 

ORDER  BY f.[file_id] 

OPTION (recompile); 

 


Look at how large and how full the files are and where they are located.Make sure the transaction log is not full!!Is_autogrow_all_files is new for SQL Server 2016. Equivalent to TF 1117 for user databases.

 

Query 2


Log space usage for current database(Log SpaceUsage)

 

SELECT Db_name(lsu.database_id) 

       AS 

       [database name], 

       db.recovery_model_desc 

       AS [recovery model], 

       Cast(total_log_size_in_bytes / 1048576.0 AS DECIMAL(10, 2)) 

       AS 

       [total log space (mb)], 

       Cast(used_log_space_in_bytes / 1048576.0 AS DECIMAL(10, 2)) 

       AS 

       [used log space (mb)], 

       Cast(used_log_space_in_percent AS DECIMAL(10, 2)) 

       AS [used log space %], 

       Cast(log_space_in_bytes_since_last_backup / 1048576.0 AS DECIMAL(10, 2)) 

       AS 

       [used log space since last backup (mb)], 

       db.log_reuse_wait_desc 

FROM   sys.dm_db_log_space_usage AS lsu WITH (nolock) 

       INNER JOIN sys.databases AS db WITH (nolock) 

               ON lsu.database_id = db.database_id 

OPTION (recompile); 

 


Look at log file size and usage, along with thelog reuse wait description for the current database.

 

Query 3


Get database scoped configuration values for current database(Database-scoped Configurations)


SELECT configuration_id, 

       NAME, 

       [value] AS [value_for_primary], 

       value_for_secondary 

FROM   sys.database_scoped_configurations WITH (nolock) 

OPTION (recompile); 

This lets you see the value of these new properties for the current database.Clear plan cache for current database.

ALTER DATABASE scoped configuration clear procedure_cache; 

ALTER DATABASE scoped configuration (transact-sql)  


Query 4

 

I/O Statistics by file for the current database(IO Stats By File)


SELECT Db_name(Db_id())                                             AS 

       [database name], 

       df.NAME                                                      AS 

       [logical name], 

       vfs.[file_id], 

       df.type_desc, 

       df.physical_name                                             AS 

       [physical name], 

       Cast(vfs.size_on_disk_bytes / 1048576.0 AS DECIMAL(10, 2))   AS 

       [size on disk(mb)], 

       vfs.num_of_reads, 

       vfs.num_of_writes, 

       vfs.io_stall_read_ms, 

       vfs.io_stall_write_ms, 

       Cast(100. * vfs.io_stall_read_ms / ( vfs.io_stall_read_ms 

                                            + vfs.io_stall_write_ms ) AS DECIMAL 

            (10, 1) 

       )                                                            AS 

       [io stall reads pct], 

       Cast(100. * vfs.io_stall_write_ms / ( vfs.io_stall_write_ms 

                                             + vfs.io_stall_read_ms ) AS DECIMAL 

            (10, 1) 

       )                                                            AS 

       [io stall writes pct], 

       ( vfs.num_of_reads + vfs.num_of_writes )                     AS 

       [writes + reads], 

       Cast(vfs.num_of_bytes_read / 1048576.0 AS DECIMAL(10, 2))    AS [mb read] 

       , 

       Cast(vfs.num_of_bytes_written / 1048576.0 AS DECIMAL(10, 2)) AS 

       [mb written], 

       Cast(100. * vfs.num_of_reads / ( vfs.num_of_reads + vfs.num_of_writes ) 

            AS 

            DECIMAL(10, 1))                                         AS 

       [# reads pct], 

       Cast(100. * vfs.num_of_writes / ( vfs.num_of_reads + vfs.num_of_writes ) 

            AS 

            DECIMAL( 

            10, 1))                                                 AS 

       [# write pct], 

       Cast(100. * vfs.num_of_bytes_read / ( vfs.num_of_bytes_read 

                                             + vfs.num_of_bytes_written ) AS 

            DECIMAL(10, 1))                                         AS 

       [read bytes pct], 

       Cast(100. * vfs.num_of_bytes_written / ( vfs.num_of_bytes_read 

                                                + vfs.num_of_bytes_written ) AS 

            DECIMAL 

            (10, 1))                                                AS 

       [written bytes pct] 

FROM   sys.Dm_io_virtual_file_stats(Db_id(), NULL) AS vfsinner 

       JOIN sys.database_files AS df WITH (nolock) 

         ON vfs.[file_id] = df.[file_id] 

OPTION (recompile);  


This helps you characterize your workload better from an I/O perspective for this database.It helps you determine whether you has an OLTP or DW/DSS type of workload.

 

Query 5

 

Get most frequently executed queries for this database(Query Execution Counts)


SELECT TOP(50) 

            LEFT(t.[text], 50)                        AS [shortquery text], 

            qs.execution_count                        AS [execution count], 

            qs.total_logical_reads                    AS [total logical reads], 

            qs.total_logical_reads/qs.execution_count AS [avg logical reads], 

            qs.total_worker_time                      AS [total worker time], 

            qs.total_worker_time/qs.execution_count   AS [avg worker time], 

            qs.total_elapsed_time                     AS [total elapsed time], 

            qs.total_elapsed_time/qs.execution_count  AS [avg elapsed time], 

            qs.creation_time                          AS [creation time]--,t.[text] as [complete query text], 

            qp.query_plan                             AS [query plan] 

            -- uncomment out these columns if not copying results to excel 

FROM        sys.dm_exec_query_stats             AS qs WITH (nolock) 

CROSS apply sys.dm_exec_sql_text(plan_handle)   AS t 

CROSS apply sys.dm_exec_query_plan(plan_handle) AS qp 

WHERE       t.dbid = db_id() 

ORDER BY    qs.execution_count DESC OPTION (recompile); 


Query 6

 

Top Cached SPs By Execution Count(SP Execution Counts)


SELECT TOP(100) p.NAME 

                AS 

                [sp name], 

                qs.execution_count, 

                Isnull(qs.execution_count / Datediff(minute, qs.cached_time, 

                                            Getdate()), 0) AS 

                [calls/minute], 

                qs.total_worker_time / qs.execution_count 

                AS [avgworkertime], 

                qs.total_worker_time 

                AS [totalworkertime], 

                qs.total_elapsed_time, 

                qs.total_elapsed_time / qs.execution_count 

                AS [avg_elapsed_time], 

                qs.cached_time 

FROM   sys.procedures AS p WITH (nolock) 

       INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (nolock) 

               ON p.[object_id] = qs.[object_id] 

WHERE  qs.database_id = Db_id() 

ORDER  BY qs.execution_count DESC 

OPTION (recompile); 


Tells you which cached stored procedures are called the most often.This helps you characterize and baseline your workload.

 

Query 7

 

Top Cached SPs By Avg Elapsed Time(SP Avg Elapsed Time)


SELECT TOP(25) 

           p.NAME AS [sp name], 

           qs.min_elapsed_time, 

           qs.total_elapsed_time/qs.execution_count AS[avg_elapsed_time], 

           qs.max_elapsed_time, 

           qs.last_elapsed_time, 

           qs.total_elapsed_time, 

           qs.execution_count, 

           Isnull(qs.execution_count/Datediff(minute, qs.cached_time, Getdate()), 0) AS [calls/minute],

           qs.total_worker_time/qs.execution_count                                   AS [avgworkertime],

           qs.total_worker_time                                                      AS [totalworkertime],

           qs.cached_timefrom sys.procedures                                         as p WITH (nolock)

INNER JOIN sys.dm_exec_procedure_stats                                               AS qs WITH (nolock)

ON         p.[object_id] = qs.[object_id] 

WHERE      qs.database_id = db_id() 

ORDER BY   avg_elapsed_time DESC OPTION (recompile); 


This helps you find high average elapsed time cached stored procedures that.May be easy to optimize with standard query tuning techniques.

 

Query 8

 

Top Cached SPs By Total Worker time. Worker time relates to CPU cost(SP Worker Time)


SELECT TOP(25) p.NAME 

               AS 

               [sp name], 

               qs.total_worker_time 

               AS [totalworkertime], 

               qs.total_worker_time / qs.execution_count 

               AS [avgworkertime], 

               qs.execution_count, 

               Isnull(qs.execution_count / Datediff(minute, qs.cached_time, 

                                           Getdate()), 0) AS 

               [calls/minute], 

               qs.total_elapsed_time, 

               qs.total_elapsed_time / qs.execution_count 

               AS [avg_elapsed_time], 

               qs.cached_time 

FROM   sys.procedures AS p WITH (nolock) 

       INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (nolock) 

               ON p.[object_id] = qs.[object_id] 

WHERE  qs.database_id = Db_id() 

ORDER  BY qs.total_worker_time DESC 

OPTION (recompile); 


This helps you find the most expensive cached stored procedures from a CPU perspective.You should look at this if you see signs of CPU pressure.

 

Query 9


SELECT TOP(25) p.NAME 

               AS 

               [SP Name], 

               qs.total_logical_reads 

               AS [TotalLogicalReads], 

               qs.total_logical_reads / qs.execution_count 

               AS [AvgLogicalReads], 

               qs.execution_count, 

               Isnull(qs.execution_count / Datediff(minute, qs.cached_time, 

                                           Getdate()), 0) AS 

               [Calls/Minute], 

               qs.total_elapsed_time, 

               qs.total_elapsed_time / qs.execution_count 

               AS [avg_elapsed_time], 

               qs.cached_time 

FROM   sys.procedures AS p WITH (nolock) 

       INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (nolock) 

               ON p.[object_id] = qs.[object_id] 

WHERE  qs.database_id = Db_id() 

ORDER  BY qs.total_logical_reads DESC 

OPTION (recompile);  


This helps you find the most expensive cached stored procedures from a memory perspective.You should look at this if you see signs of memory pressure.

 

Query 10

 

Top Cached SPs By Total Physical Reads. Physical reads relate to disk read I/O pressure(SP Physical Reads)


SELECT TOP(25) p.NAME                                       AS [SP Name], 

               qs.total_physical_reads                      AS 

               [TotalPhysicalReads], 

               qs.total_physical_reads / qs.execution_count AS 

               [AvgPhysicalReads], 

               qs.execution_count, 

               qs.total_logical_reads, 

               qs.total_elapsed_time, 

               qs.total_elapsed_time / qs.execution_count   AS 

               [avg_elapsed_time], 

               qs.cached_time 

FROM   sys.procedures AS p WITH (nolock) 

       INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (nolock) 

               ON p.[object_id] = qs.[object_id] 

WHERE  qs.database_id = Db_id() 

       AND qs.total_physical_reads > 0 

ORDER  BY qs.total_physical_reads DESC, 

          qs.total_logical_reads DESC 

OPTION (recompile);


This helps you find the most expensive cached stored procedures from a read I/O perspective.You should look at this if you see signs of I/O pressure or of memory pressure.

 

Query 11

 

Top Cached SPs By Total Logical Writes(SP Logical Writes). Logical writes relate to both memory and disk I/O pressure.


SELECT TOP(25) p.NAME

               AS

               [SP Name],

               qs.total_logical_writes

               AS [TotalLogicalWrites],

               qs.total_logical_writes / qs.execution_count

               AS [AvgLogicalWrites],

               qs.execution_count,

               Isnull(qs.execution_count / Datediff(minute, qs.cached_time,Getdate()), 0) AS

[Calls/Minute],

              qs.total_elapsed_time,

               qs.total_elapsed_time / qs.execution_count 

               AS [avg_elapsed_time],

               qs.cached_time

FROM   sys.procedures AS p WITH (nolock)

  INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (nolock)

               ON p.[object_id] = qs.[object_id]

WHERE  qs.database_id = Db_id()

       AND qs.total_logical_writes > 0

ORDER  BY qs.total_logical_writes DESC

OPTION (recompile); 


This helps you find the most expensive cached stored procedures from a read I/O perspective.You should look at this if you see signs of I/O pressure or of memory pressure.

 

Query 12

 

Lists the top statements by average input/output usage for the current database(Top IO Statements)


SELECT TOP(50) Object_name(qt.objectid, dbid)                     AS [SP Name], 

               ( qs.total_logical_reads 

                 + qs.total_logical_writes ) / qs.execution_count AS [Avg IO], 

               qs.execution_count                                 AS 

               [Execution Count], 

               Substring(qt.[text], qs.statement_start_offset / 2, ( 

               CASE 

                 WHEN qs.statement_end_offset = -THEN 

                 Len(CONVERT(NVARCHAR(max), qt.[text])) 

                 * 2 

                 ELSE qs.statement_end_offset 

               END - qs.statement_start_offset ) / 2)             AS 

               [Query Text] 

FROM   sys.dm_exec_query_stats AS qs WITH (nolock) 

       CROSS apply sys.Dm_exec_sql_text(qs.sql_handle) AS qt 

WHERE  qt.[dbid] = Db_id() 

ORDER  BY [avg io] DESC 

OPTION (recompile);


Helps you find the most expensive statements for I/O by SP.

 

Query 13

 

Possible Bad NC Indexes (writes > reads)(Bad NC Indexes)


SELECT Object_name(s.[object_id])                          AS [Table Name], 

i.NAME                                                    AS 

       [Index Name],

       i.index_id, 

       i.is_disabled, 

       i.is_hypothetical, 

       i.has_filter, 

       i.fill_factor, 

       user_updates                                              AS 

       [Total Writes], 

       user_seeks + user_scans + user_lookups                    AS 

       [Total Reads], 

       user_updates - ( user_seeks + user_scans + user_lookups ) AS [Difference] 

FROM   sys.dm_db_index_usage_stats AS s WITH (nolock) 

  INNER JOIN sys.indexes AS i WITH (nolock) 

               ON s.[object_id] = i.[object_id] 

                  AND i.index_id = s.index_id 

WHERE  Objectproperty(s.[object_id], 'IsUserTable') = 1 

       AND s.database_id = Db_id() 

  AND user_updates > ( user_seeks + user_scans + user_lookups ) 

       AND i.index_id > 1 

ORDER  BY [difference] DESC, 

          [total writes] DESC, 

          [total reads] ASC 

OPTION (recompile);  


Look for indexes with high numbers of writes and zero or very low numbers of reads.Consider your complete workload, and how long your instance has been running.Investigate further before dropping an index!

 

Query 14

 

Missing Indexes for current database by Index Advantage(Missing Indexes)


SELECT DISTINCT CONVERT(DECIMAL(18, 2), 

user_seeks * avg_total_user_cost * (  avg_user_impact * 0.01  ) AS

                  [index_advantage],

                  migs.last_user_seek, 

                 mid.[statement]  AS [Database.Schema.Table], 

                mid.equality_columns, 

                mid.inequality_columns, 

                 mid.included_columns,    

              migs.unique_compiles, 

                 migs.user_seeks,  

                migs.avg_total_user_cost,  

                migs.avg_user_impact,    

              Object_name(mid.[object_idAS [Table Name], 

                 p.rows  AS [Table Rows]  FROM   sys.dm_db_missing_index_group_stats AS migs WITH (nolock)         INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (nolock)                 ON migs.group_handle = mig.index_group_handle         INNER JOIN sys.dm_db_missing_index_details AS mid WITH (nolock)                 ON mig.index_handle = mid.index_handle         INNER JOIN sys.partitions AS p WITH (nolock)ON p.[object_id] = mid.[object_id]  WHERE  mid.database_id = Db_id() 


Look at index advantage, last user seek time,number of user seeks to help determine source and importance.SQL Server is overly eager to add included columns, so beware.Do not just blindly add indexes that show up from this query!!!

 

Query 15

 

Find missing index warnings for cached plans inthe current database(Missing IndexWarnings)Note: This query could take some time on a busy instance.


SELECT TOP(25) Object_name(objectid) AS [ObjectName], 

                query_plan, 

               cp.objtype, 

               cp.usecounts, 

               cp.size_in_bytes 

FROM   sys.dm_exec_cached_plans AS cp WITH (nolock) 

       CROSS apply sys.Dm_exec_query_plan(cp.plan_handle) AS qp 

WHERE  Cast(query_plan AS NVARCHAR(max)) LIKE N'%MissingIndex%' 

       AND dbid = Db_id() 

ORDER  BY cp.usecounts DESC 

OPTION (recompile); 


Helps you connect missing indexes to specific stored procedures or queries.This can help you decide whether to add them or not.

 

Query 16

 

Breaks down buffers used by current database by object (table, index) in the buffer cache(Buffer Usage)Note: This query could take some time on a busy instance


SELECT Object_name(p.[object_id])               AS [Object Name], 

       p.index_id, 

       Cast(Count(*) / 128.0 AS DECIMAL(10, 2)) AS [Buffer size(MB)], 

       Count(*)                                 AS [BufferCount], 

       p.rows                                   AS [Row Count], 

       p.data_compression_desc                  AS [Compression Type] 

FROM   sys.allocation_units AS a WITH (nolock) 

       INNER JOIN sys.dm_os_buffer_descriptors AS b WITH (nolock) 

               ON a.allocation_unit_id = b.allocation_unit_id 

       INNER JOIN sys.partitions AS p WITH (nolock) 

               ON a.container_id = p.hobt_id 

WHERE  b.database_id = CONVERT(INT, Db_id()) 

       AND p.[object_id] > 100 

GROUP  BY p.[object_id], 

          p.index_id, 

          p.data_compression_desc, 

          p.[rows] 

ORDER  BY [buffercount] DESC 

OPTION (recompile);


Tells you what tables and indexes are using the most memory in the buffer cache.It can help identify possible candidates for data compression.

 

Query 17

 

Get Table names, row counts, and compression status for clustered index or heap (Table Sizes)


SELECT Object_name(object_id) AS [ObjectName], 

       Sum(rows)              AS [RowCount], 

       data_compression_desc  AS [CompressionType] 

FROM   sys.partitions WITH (nolock) 

WHERE  index_id < 2 --ignore the partitions from the non-clustered index if any 

       AND Object_name(object_id) NOT LIKE N'sys%' 

       AND Object_name(object_id) NOT LIKE N'queue_%' 

       AND Object_name(object_id) NOT LIKE N'filestream_tombstone%' 

       AND Object_name(object_id) NOT LIKE N'fulltext%' 

       AND Object_name(object_id) NOT LIKE N'ifts_comp_fragment%' 

       AND Object_name(object_id) NOT LIKE N'filetable_updates%' 

       AND Object_name(object_id) NOT LIKE N'xml_index_nodes%' 

       AND Object_name(object_id) NOT LIKE N'sqlagent_job%' 

       AND Object_name(object_id) NOT LIKE N'plan_persist%' 

GROUP  BY object_id, 

          data_compression_desc 

ORDER  BY Sum(rows) DESC 

OPTION (recompile); 


Gives you an idea of table sizes, and possible data compression opportunities.

 

Query 18

 

Get some key table properties(Table Properties)


SELECT Object_name(t.[object_id]) AS [ObjectName], 

       p.[rows]                   AS [Table Rows], 

       p.index_id, 

       p.data_compression_desc    AS [Index Data Compression], 

       t.create_date, 

       t.lock_on_bulk_load, 

       t.is_replicated, 

       t.has_replication_filter, 

       t.is_tracked_by_cdc, 

       t.lock_escalation_desc, 

       t.is_memory_optimized, 

       t.durability_desc, 

       t.is_filetable, 

       t.temporal_type_desc, 

       t.is_remote_data_archive_enabled, 

       t.remote_data_archive_migration_state_desc, 

       t.is_external -- new for SQL Server 2016 

FROM   sys.tables AS t WITH (nolock) 

       INNER JOIN sys.partitions AS p WITH (nolock) 

               ON t.[object_id] = p.[object_id] 

WHERE  Object_name(t.[object_id]) NOT LIKE N'sys%' 

ORDER  BY Object_name(t.[object_id]), 

          p.index_id 

OPTION (recompile);  


Gives you some good information about your tables.Is Memory optimized and durability description are Hekaton-related properties that were new in SQL Server 2014.temperal_type_desc,is_remote_data_archive_enabled,remote_data_archive_migration_state_desc,is_external are new in SQL Server 2016. 

 

Query 19

 

When were Statistics last updated on all indexes?(Statistics Update)


SELECT Schema_name(o.schema_id) + N'.' + o.NAME AS [Object Name], 

       o.type_desc                              AS [Object Type], 

       i.NAME                                   AS [Index Name], 

       Stats_date(i.[object_id], i.index_id)    AS [Statistics Date], 

       s.auto_created, 

       s.no_recompute, 

       s.user_created, 

       s.is_incremental, 

       s.is_temporary, 

       st.row_count, 

       st.used_page_count 

FROM   sys.objects AS o WITH (nolock) 

       INNER JOIN sys.indexes AS i WITH (nolock) 

               ON o.[object_id] = i.[object_id] 

       INNER JOIN sys.stats AS s WITH (nolock) 

               ON i.[object_id] = s.[object_id] 

                  AND i.index_id = s.stats_id 

       INNER JOIN sys.dm_db_partition_stats AS st WITH (nolock) 

               ON o.[object_id] = st.[object_id] 

                  AND i.[index_id] = st.[index_id] 

WHERE  o.[type] IN ( 'U', 'V' ) 

       AND st.row_count > 0 

ORDER  BY Stats_date(i.[object_id], i.index_id) DESC 

OPTION (recompile); 


Helps discover possible problems with out-of-date statistics.Also gives you an idea which indexes are the most active.

 

Query 20

 

Look at most frequently modified indexes and statistics(Volatile Indexes)


SELECT o.NAME AS [Object Name], 

       o.[object_id], 

       o.type_desc, 

       s.NAME AS [Statistics Name], 

       s.stats_id, 

       s.no_recompute, 

       s.auto_created, 

       sp.modification_counter, 

       sp.rows, 

       sp.rows_sampled, 

       sp.last_updated 

FROM   sys.objects AS o WITH (nolock) 

       INNER JOIN sys.stats AS s WITH (nolock) 

               ON s.object_id = o.object_id 

       CROSS apply sys.Dm_db_stats_properties(s.object_id, s.stats_id) AS sp 

WHERE  o.type_desc NOT IN ( N'SYSTEM_TABLE', N'INTERNAL_TABLE' ) 

       AND sp.modification_counter > 0 

ORDER  BY sp.modification_counter DESC, 

          o.NAME 

 

OPTION (recompile); 


Query 21

 

Get fragmentation info for all indexes above a certain size in the current database ( Index Fragmentation)

Note: This query could take some time on a very large database


SELECT Db_name(ps.database_id)    AS [Database Name], 

       Schema_name(o.[schema_id]) AS [Schema Name], 

       Object_name(ps.object_id)  AS [Object Name], 

       i.NAME                     AS [Index Name], 

       ps.index_id, 

       ps.index_type_desc, 

       ps.avg_fragmentation_in_percent, 

       ps.fragment_count, 

       ps.page_count, 

       i.fill_factor, 

       i.has_filter, 

       i.filter_definition, 

       i.allow_page_locks 

FROM   sys.Dm_db_index_physical_stats(Db_id(), NULL, NULL, NULL, N'LIMITED') AS 

       ps 

       INNER JOIN sys.indexes AS i WITH (nolock) 

               ON ps.[object_id] = i.[object_id] 

                  AND ps.index_id = i.index_id 

       INNER JOIN sys.objects AS o WITH (nolock) 

               ON i.[object_id] = o.[object_id] 

WHERE  ps.database_id = Db_id() 

       AND ps.page_count > 2500 

ORDER  BY ps.avg_fragmentation_in_percent DESC 

OPTION (recompile); 


Helps determine whether you have framentation in your relational indexes and how effective your index maintenance strategy.

 

Query 22

 

Index Read/Write stats (all tables in current DB) ordered by Reads (Overall Index Usage - Reads)


SELECT Object_name(i.[object_id])                   AS [ObjectName], 

       i.NAME                                       AS [IndexName], 

       i.index_id, 

       s.user_seeks, 

       s.user_scans, 

       s.user_lookups, 

       s.user_seeks + s.user_scans + s.user_lookups AS [Total Reads], 

       s.user_updates                               AS [Writes], 

       i.type_desc                                  AS [Index Type], 

       i.fill_factor                                AS [Fill Factor], 

       i.has_filter, 

       i.filter_definition, 

       s.last_user_scan, 

       s.last_user_lookup, 

       s.last_user_seek 

FROM   sys.indexes AS i WITH (nolock) 

       LEFT OUTER JOIN sys.dm_db_index_usage_stats AS s WITH (nolock) 

                    ON i.[object_id] = s.[object_id] 

                       AND i.index_id = s.index_id 

                       AND s.database_id = Db_id() 

WHERE  Objectproperty(i.[object_id], 'IsUserTable') = 1 

ORDER  BY s.user_seeks + s.user_scans + s.user_lookups DESC 

OPTION (recompile); -- Order by reads 


Show which indexes in the current database are most active for Writes

 

Query 23

 

Get in-memory OLTP index usage(XTP Index Usage)


SELECT Object_name(i.[object_id]) AS [Object Name], 

       i.index_id, 

       i.NAME, 

       i.type_desc, 

       xis.scans_started, 

       xis.scans_retries, 

       xis.rows_touched, 

       xis.rows_returned 

FROM   sys.dm_db_xtp_index_stats AS xis WITH (nolock) 

       INNER JOIN sys.indexes AS i WITH (nolock) 

               ON i.[object_id] = xis.[object_id] 

                  AND i.index_id = xis.index_id 

ORDER  BY Object_name(i.[object_id]) 

OPTION (recompile);


This gives you some index usage statistics for in-memory OLTP.Returns no data if you are not using in-memory OLTP.

 

Query 24

 

Get lock waits for current database(Lock Waits)


SELECT o.NAME                        AS [table_name], 

       i.NAME                        AS [index_name], 

       ios.index_id, 

       ios.partition_number, 

       Sum(ios.row_lock_wait_count)  AS [total_row_lock_waits], 

       Sum(ios.row_lock_wait_in_ms)  AS [total_row_lock_wait_in_ms], 

       Sum(ios.page_lock_wait_count) AS [total_page_lock_waits], 

       Sum(ios.page_lock_wait_in_ms) AS [total_page_lock_wait_in_ms], 

       Sum(ios.page_lock_wait_in_ms) 

       + Sum(row_lock_wait_in_ms)    AS [total_lock_wait_in_ms] 

FROM   sys.Dm_db_index_operational_stats(Db_id(), NULL, NULL, NULL) AS ios 

       INNER JOIN sys.objects AS o WITH (nolock) 

               ON ios.[object_id] = o.[object_id] 

       INNER JOIN sys.indexes AS i WITH (nolock) 

               ON ios.[object_id] = i.[object_id] 

                  AND ios.index_id = i.index_id 

WHERE  o.[object_id] > 100 

GROUP  BY o.NAME, 

          i.NAME, 

          ios.index_id, 

          ios.partition_number 

HAVING Sum(ios.page_lock_wait_in_ms) 

       + Sum(row_lock_wait_in_ms) > 0 

ORDER  BY total_lock_wait_in_ms DESC 

OPTION (recompile);


This query is helpful for troubleshooting blocking and deadlocking issues.

 

Query 25

 

Look at UDF execution statistics(UDF Statistics)


SELECT Object_name(object_id)    AS [Function Name], 

       execution_count, 

       total_elapsed_time / 1000 AS [time_milliseconds], 

       fs.[type_desc] 

FROM   sys.dm_exec_function_stats AS fs WITH (nolock) 

WHERE  database_id = Db_id() 

ORDER  BY Object_name(object_id) 

OPTION (recompile); 


New for SQL Server 2016: Helps you investigate UDF Performance Issues


Query 26

 

Get QueryStore Options for this database(QueryStoreOptions)


SELECT actual_state, 

       actual_state_desc, 

       readonly_reason, 

       current_storage_size_mb, 

       max_storage_size_mb 

FROM   sys.database_query_store_options WITH (nolock) 

OPTION (recompile); 


New for SQL Server 2016 : Requires that QueryStore is enabled for this database.

 

Query 27

 

Get highest aggregate duration queries over last hour (High Aggregate Duration Queries)


WITH aggregateddurationlasthour 

     AS (SELECT q.query_id, 

                Sum(count_executions * avg_duration) AS total_duration, 

                Count (DISTINCT p.plan_id)           AS number_of_plans 

         FROM   sys.query_store_query_text AS qt WITH (nolock) 

                INNER JOIN sys.query_store_query AS q WITH (nolock) 

                        ON qt.query_text_id = q.query_text_id 

                INNER JOIN sys.query_store_plan AS p WITH (nolock) 

                        ON q.query_id = p.query_id 

                INNER JOIN sys.query_store_runtime_stats AS rs WITH (nolock) 

                        ON rs.plan_id = p.plan_id 

                INNER JOIN sys.query_store_runtime_stats_interval AS rsi WITH ( 

                           nolock 

                           ) 

                        ON rsi.runtime_stats_interval_id = 

                           rs.runtime_stats_interval_id 

         WHERE  rsi.start_time >= Dateadd(hour, -1, Getutcdate()) 

                AND rs.execution_type_desc = N'Regular' 

         GROUP  BY q.query_id), 

     orderedduration 

     AS (SELECT query_id, 

                total_duration, 

                number_of_plans, 

                Row_number () 

                  OVER ( 

                    ORDER BY total_duration DESC, query_id) AS RN 

         FROM   aggregateddurationlasthour) 

SELECT Object_name(q.object_id)   AS [Containing Object], 

       qt.query_sql_text, 

       od.total_duration          AS [Total Duration (microsecs)], 

       od.number_of_plans         AS [Plan Count], 

       p.is_forced_plan, 

       p.is_parallel_plan, 

       p.is_trivial_plan, 

       q.query_parameterization_type_desc, 

       p.[compatibility_level], 

       p.last_compile_start_time, 

       q.last_execution_time, 

       CONVERT(XML, p.query_plan) AS query_plan_xml 

FROM   orderedduration AS od 

       INNER JOIN sys.query_store_query AS q WITH (nolock) 

               ON q.query_id = od.query_id 

       INNER JOIN sys.query_store_query_text AS qt WITH (nolock) 

               ON q.query_text_id = qt.query_text_id 

       INNER JOIN sys.query_store_plan AS p WITH (nolock) 

               ON q.query_id = p.query_id 

WHERE  od.rn <= 50 

ORDER  BY total_duration DESC 

OPTION (recompile); 


New for SQL Server 2016:Requires that QueryStore is enabled for this database.

 

Query 28

 

Look at recent Full backups for the current database(Recent Full Backups)


SELECT TOP (30) bs.machine_name, 

                bs.server_name, 

                bs.database_name 

                AS [Database Name], 

                bs.recovery_model, 

                CONVERT (BIGINT, bs.backup_size / 1048576) 

                AS [Uncompressed Backup Size (MB)], 

                CONVERT (BIGINT, bs.compressed_backup_size / 1048576) 

                AS 

                [Compressed Backup Size (MB)], 

                CONVERT (NUMERIC (20, 2), ( CONVERT (FLOAT, bs.backup_size) / 

                CONVERT (FLOAT, bs.compressed_backup_size) )) AS 

                [Compression Ratio], 

                bs.has_backup_checksums, 

                bs.is_copy_only, 

                bs.encryptor_type, 

                Datediff (second, bs.backup_start_date, bs.backup_finish_date) 

                AS 

                [Backup Elapsed Time (sec)], 

                bs.backup_finish_date 

                AS [Backup Finish Date] 

FROM   msdb.dbo.backupset AS bs WITH (nolock) 

WHERE  bs.database_name = Db_name(Db_id()) 

       AND bs.[type] = 'D' -- Change to L if you want Log backups 

ORDER  BY bs.backup_finish_date DESC 

OPTION (recompile); 


Are your backup sizes and times changing over time? Are you using backup compression?Have you done any backup tuning with striped backups, or changing the parameters of the backup command?

 


Statistics Says It All

16

Years of Experience

3000

Gratified Students

100

Training Batches

9600

Training Hours


Subscribe

Please subscribe our technical blog to get recent updates.

Empire Data Systems

Social Links