Skip to content

Instantly share code, notes, and snippets.

@akrisiun
Forked from Velniai/Indexes Usage Stats.sql
Created September 16, 2019 05:36
Show Gist options
  • Save akrisiun/525666a904c941b97015a523878aeae9 to your computer and use it in GitHub Desktop.
Save akrisiun/525666a904c941b97015a523878aeae9 to your computer and use it in GitHub Desktop.
[Index Maintainance] #sql #index #dmv
DECLARE @TableName VARCHAR(20) = NULL
SELECT TableName = OBJECT_NAME(S.object_id),
IndexName = I.name,
UserSeeks = S.user_seeks,
UserScans = S.user_scans,
UserLookups = S.user_lookups,
UserUpdates = S.user_updates ,
IsPrimaryKey = i.is_primary_key
FROM sys.dm_db_index_usage_stats S
INNER JOIN sys.indexes AS I
ON I.object_id = S.object_id AND
I.index_id = S.index_id
WHERE OBJECTPROPERTY(S.[OBJECT_ID],'IsUserTable') = 1 AND
(OBJECT_NAME(S.[OBJECT_ID]) = @TableName OR @TableName IS NULL)
OPTION (FORCE ORDER)

Statistics

DBCC SHOW_STATISTICS('schema.Table','IndexName')

  • Metadata about the statistics including date and time of the last update of the statistics, number of rows in the table, number of rows sampled, number of steps in the histogram, index density, average key length, whether the index contains string summary statistics, filtered predicate for statistics if applicable, and number of rows before applying the filter.
  • Index densities for the combination of columns in the index.
  • A histogram of up to 200 sample values in the first key column in the indexv

STATS_DATE

SELECT	name AS ObjectName,
	STATS_DATE(object_id, stats_id) AS UpdateDate
FROM 	sys.stats
WHERE 	object_id = OBJECT_ID('Sales.Customers');

Deadlocks

SQL Server Profiler deadlock graph

If you use SQL Server Profiler to capture a deadlock graph, you must configure the trace
before deadlocks occur. Events:

  • Deadlock graph
  • Lock:Deadlock
  • Lock:Deadlock Chain

Memory Optimize Table

  • sys.sp_xtp_control_proc_exec_stats Use this system stored procedure to enable statistics collection for your SQL Server instance at the procedure level.
  • sys.sp_xtp_control_query_exec_stats Use this system stored procedure to enable statistics collection at the query level for selected natively compiled stored procedures.

DMOs

sys.dm_exec_* Connections, sessions, requests, and query execution
sys.dm_os_* Information for the operating system on which SQL Server runs
sys.dm_tran_* Details about transactions
sys.dm_io_* IO processes
sys.dm_db_* Database-scoped information
Cache
  • sys.dm_os_memory_cache_counters View the current state of the cache.

  • sys.dm_os_sys_memory View resource usage information for the server, including total physical and available memory and high or low memory state.

  • sys.dm_os_memory_clerks View usage information by memory clerk processes that manage memory for SQL Server.

  • sys.dm_tran_locks Use this DMV to view all current locks, the lock resources, lock mode, and other related information.The sys.dm_tran_locks DMV provides you with information about existing locks and locks that have been requested but not yet granted in addition to details about the resource for which the lock is requested. You can use this DMV only to view information at the current point in time. It does not provide access to historical information about locks.

  • sys.dm_os_waiting_tasks Use this DMV to see which tasks are waiting for a resource. Whenever a user asks you why a query is taking longer to run than usual, a review of this DMV should be one of your standard troubleshooting steps

  • sys.dm_os_wait_stats Use this DMV to see how often processes are waiting while locks are taken.The sys.dm_os_wait_stats DMV is an aggregate view of all waits that occur when a requested resource is not available, a worker thread is idle typically due to background tasks, or an external event must complete first. Potential issues:

    • CPU pressure Compare the signal wait time to the total wait time to determine the relative percentage of time that a thread has to wait for its turn to run on the CPU. When this value is relatively high, it can be an indicator that the CPU is overwhelmed by queries that require tuning or your server needs more CPU. You can confirm whether the issue is related to CPU by checking the runnable_tasks_count column in the sys.dm_os_schedulers DMV to see if there is a high number of tasks in the runnable queue. You might also see a higher occurrence of the SOS_SCHEDULER_YIELD wait type if the CPU is under pressure. In addition, you can monitor CPU-related performance counters as described in Skill 4.4.
    • IO issues If tasks are waiting for the IO subsystem, you will see waits that contain IO in the name. In particular, monitor the trend in average wait time which is calculated by dividing wait_time_ms by waiting_tasks_count. If it starts trending upward, investigate IO using performance counters. Two wait types that will appear frequently in this DMV when IO issues exist are ASYNC_IO_COMPLETION and IO_COMPLETION. Check physical disk performance counters to confirm this diagnosis, which we describe in the next section, “Troubleshoot and analyze storage, IO, and cache issues.” Consider adding indexes to reduce IO contention. You might also see PAGEIOLATCH waits when a thread is waiting for latches to release after writing a data page in memory to disk or WRITELOG waits when the log management system is waiting to flush to disk. These wait types can indicate either an IO subsystem problem or a memory problem. To narrow down the possibilities, you need to check IO statistics by using sys.dm_io_virtual_file_stats and by reviewing IO-related performance counters.
    • Memory pressure The PAGEIOLATCH wait might also indicate memory pressure instead of an IO subsystem problem. It appears when SQL Server does not have enough free memory available for the buffer pool. Check the Page Life Expectancy performance counter to see if it is dropping as compared to a baseline value to confirm whether memory is the reason for this wait type. If you see an increase in CXPACKET waits in conjunction with PAGEIOLATCH waits, the culprit could be a query plan using large table or index scans. Another indicator of a memory pressure issue is the RESOURCE_SEMAPHORE wait. It occurs when a query requests more memory than is currently available. You can check the sys.dm_exec_query_memory_grants DMV and combine it with sys.dm_exec_sql_text and sys.dm_exec_sql_plan DMVs to find the memoryintensive queries and review their query plans.
  • sys.dm_db_index_usage_stats Use this DMV to review the use of indexes to resolve queries. Counts in this DMV are reset when the server restarts or when an index is dropped and recreated.

SELECT	OBJECT_NAME(ixu.object_id, DB_ID('WideWorldImporters')) AS
	[object_name] ,
	ix.[name] AS index_name ,
	ixu.user_seeks + ixu.user_scans + ixu.user_lookups AS
	user_reads,
	ixu.user_updates AS user_writes
FROM 	sys.dm_db_index_usage_stats ixu
	INNER JOIN WideWorldImporters.sys.indexes ix ON
		ixu.[object_id] = ix.[object_id] AND
		ixu.index_id = ix.index_id
WHERE 	ixu.database_id = DB_ID('WideWorldImporters')
ORDER 	BY user_reads DESC;
  • sys.dm_db_index_physical_stats Use this dynamic management function (DMF) to check the overall status of indexes in a database.
DECLARE @db_id SMALLINT, @object_id INT;
SET @db_id = DB_ID(N'WideWorldImporters');
SET @object_id = OBJECT_ID(N'WideWorldImporters.Sales.Orders');
SELECT	ixs.index_id AS idx_id,
	ix.name AS ObjectName,
	index_type_desc,
	page_count,
	avg_page_space_used_in_percent AS AvgPageSpacePct,
	fragment_count AS frag_ct,
	avg_fragmentation_in_percent AS AvgFragPct
FROM 	sys.dm_db_index_physical_stats(@db_id, @object_id, NULL, NULL , 'Detailed') ixs
	INNER JOIN sys.indexes ix ON
		ixs.index_id = ix.index_id AND
		ixs.object_id = ix.object_id
ORDER 	BY avg_fragmentation_in_percent DESC;
  • sys.dm_db_missing_index_details Use this DMV to identify the columns used for equality and inequality predicates.
  • sys.dm_db_missing_index_groups Use this DMV as an intermediary between sys.dm_db_index_details and sys.dm_db_missing_group_stats.
  • sys.dm_db_missing_index_group_stats Use this DMV to retrieve metrics on a group of missing indexes.

Query Plans

  • SET SHOWPLAN_XML ON statement instructs SQL Server to generate the estimated plan without executing the query.
  • SET SHOWPLAN_TEXT ON Returns a single column containing a hierarchical tree that describes the operations and includes the physical operator and optionally the logical operator.
  • SET SHOWPLAN_ALL ON Returns the same information as SET SHOWPLAN_TEXT except the information is spread across a set of columns in which you can more easily see property values for each operator.

Extended Events

Using Extended Events is a lightweight approach to capturing query plans. There are two Extended Events that you can use to review query plans:

  • query_pre_execution_showplan This Extended Event captures the estimated query plan for a query. An estimated query plan is prepared without executing the query.
  • query_post_execution_showplan This Extended Event captures the actual query plan for a query. An actual query plan is the estimated query plan that includes runtime information. For this reason, it is not available until after the query executes.

SQL Trace

Although SQL Trace is designated as a deprecated feature and will be removed from a future release of SQL Server, it remains an available option in SQL Server 2016. You can define server-side traces by using system stored procedures and then run these traces on demand or on a scheduled basis. As an alternative, you can use SQL Server Profiler as a client-side option. The overhead of running server-side traces is much less than the overhead of using SQL Server Profiler, but the overhead is still significant. Therefore, take care when using SQL Trace in a production environment regardless of the approach you take and disable tracing as soon as possible.

Server-side tracing

  • sp_trace_create This procedure creates a new trace and defines a file into which SQL Server stores trace data. It returns a trace ID that you reference in the other procedures to manage the trace.
  • sp_trace_setevent This procedure must be called once for each data column of the events to capture in the trace. That means you must call this procedure many times for any single trace. When you call this procedure, you pass in the following arguments, the trace identifier captured as output when you create the trace, the event identifier, the column identifier, and the status of ON (1) or OFF (0).
  • sp_trace_setfilter This procedure must be called once for each filter on an event data column.
  • sp_trace_setstatus This procedure starts, stops, or removes a trace. It must be stopped and removed before you can open the related trace file.

Client-side tracing

You can use SQL Server Profiler instead of manually creating the many stored procedures to define a trace when you need to capture a query plan. On the File menu, click New Trace, and then connect to the server on which you want to run the trace. In the Trace Properties dialog box, click the Events Selection tab and then select the Show All Events checkbox. Expand the Performance node, and select one or more of the following checkboxes:

  • Showplan XML This event is raised when SQL Server selects an estimated query plan.
  • Showplan XML For Query Compile This event is raised when SQL Server compiles a query and produces an estimated query plan which it adds to the query plan cache. Generally, this event is raised only once for a query unless the query requires recompilation.
  • Showplan XML Statistics Profile This event is raised after SQL Server executes a query and has generated an actual query plan.

Query Store

  • Data Flush Interval (Minutes) The frequency in minutes at which SQL Server writes data collected by the query store to disk.
  • Statistics Collection Interval The granularity of time for which SQL Server aggregates runtime execution statistics for the query store. You can choose one of the following intervals: 1 minute, 5 minutes, 10 minutes, 15 minutes, 30 minutes, 1 hour, or 1 day. If you capture data at a high frequency, bear in mind that the query store requires more space to store more finely grained data.
  • Max Size (MB) The maximum amount of space allocated to the query store. The default value is 100 MB per database. If your database is active, this value might not be large enough to store query plans and related information.
  • Query Store Capture Mode The specification of the types of queries for which SQL Server captures data for the query store. You can choose one of the following options:
    • None The query store stops collecting data for new queries, but continues capturing data for existing queries.
    • All The query store captures data for all queries.
    • Auto The query store captures data for relevant queries. It ignores infrequent queries and queries with insignificant compile and execution duration.
  • Size Based Cleanup Mode The specification of whether the cleanup process activates when the query store data approaches its maximum size (Auto) or never runs (OFF).
  • Stale Query Threshold (Days) The number of days that SQL Server keeps data in the query store.
ALTER DATABASE <databasename>
SET QUERY_STORE = ON
(
OPERATION_MODE = READ_WRITE ,
CLEANUP_POLICY = ( STALE_QUERY_THRESHOLD_DAYS = 30 ),
DATA_FLUSH_INTERVAL_SECONDS = 3000,
MAX_STORAGE_SIZE_MB = 500,
INTERVAL_LENGTH_MINUTES = 50
);

Query Store components

The query store captures information about query plans and runtime execution statistics until the maximum space allocation is reached. You can review this data in the following DMVs:

  • sys.query_store_plan Query plan information, such as Showplan XML, the number of compilations, the date and time of the initial and last compilations, the last execution date and time, and the average and most recent duration of compilation, among other details. The query plan available in this DMV is the estimated plan only.
  • sys.query_store_query Aggregated runtime execution statistics for a query, including CPU binding, memory, optimization, and compilation statistics. This information is stored at the statement level and not at the batch level which is different from the behavior of sys.dm_exec_query_stats.
  • sys.query_store_query_text The text of the executed query.
  • sys.query_store_runtime_stats Runtime execution statistics for a query, such as first and last execution date and time, the number of executions, statistics (average, last, minimum, maximum, and standard deviation) for query duration, CPU time, logical IO reads and writes, physical IO reads and writes, CLR time, DOP, maximum used memory, and row counts.
  • sys.query_store_runtime_stats_interval The start and end times defining the intervals during which SQL Server collects runtime execution statistics for the query store.
  • sp_query_store_flush_db Flush the portion of the query store currently in memory to disk. This stored procedure takes no arguments.
  • sp_query_store_force_plan Force SQL Server to use a specified query plan for a specified query. You provide identifiers for the query and plan as arguments for this stored procedure.
  • sp_query_store_remove_plan Remove a specified query plan from the query store.
  • p_query_store_remove_query Remove a specified query from the query store, in addition to the query plans and runtime execution statistics related to it.
  • sp_query_store_reset_exec_stats Reset the runtime execution statistics for a specified plan.
  • sp_query_store_unforce_plan Keep a specified query plan in the query store, but no longer force SQL Server to use it for a specified query.

Elastic Scale for Azure SQL Database

You must use the elastic database client library to implement standard sharding patterns in a SQL Database by calling its features in your elastic scale application. You use it to perform operations across the all shards as a unit or to perform operations on individual shards, as shown in Figure 4-39. The elastic database client library provides the following features:

  • Shard map management You first register each database as a shard, and then define a shard map manager that directs connection requests to the correct shard by using a sharding key or a key range. A sharding key is data such as a customer ID number that the database engine uses to keep related transactions in one database.
  • Data-dependent routing Rather than define a connection in your application, you can use this feature to automatically assign a connection to the correct shard.
  • Multishard querying The database engine uses this feature to process queries in parallel across separate shards and then combine the results into a single result set.
  • Shard elasticity This feature monitors resource consumption for the current workload and dynamically allocates more resource as necessary and shrinks the database to its normal state when those resources are no longer required.

Service tier or edition

  • Express This edition is a free version of SQL Server with limited features that you can use for small applications and Web sites. The maximum database size supported by this edition is 10 GB. It uses up to 1 GB memory and to the lesser of 1 physical processor or 4 cores. There are three types of SQL Server 2016 Express from which to choose:
    • LocalDB You use LocalDB for a simple application with a local embedded database that runs in single-user mode.
    • Express You use Express when your application requires a small database only and does not require any other components packaged with SQL Server in the Standard edition. You can install this edition on a server and then enable remote connections to support multiple users.
    • Express with Advanced Services This edition includes the database engine as well as Full Text Search and Reporting Services.
  • Web This edition is scalable up to 64 GB of memory and the lesser of 4 physical processors or 16 cores with a maximum database size of 524 PB. It includes the database engine, but without support for availability groups and other highavailability features. It also does not include many of the advanced security and replication features available in Standard or Enterprise edition, nor does it include the business intelligence components such as Analysis Services and Reporting Services, among others. Web edition is intended for use only by Web hosters and third-party software service providers.
  • Standard This edition scales to 128 GB of memory and the lesser of 4 physical processors or 24 cores. The maximum database size with Standard edition is 524 PB. This edition includes core database and business intelligence functionality and includes basic high-availability and disaster recovery features, new security features such as row-level security and dynamic data masking, and access to non-relational data sources by using JSON and PolyBase.
  • Enterprise This edition includes all features available in the SQL Server platform and provides the highest scalability, greatest number of security features, and the most advanced business intelligence and analytics features. Like Standard edition, Enterprise edition supports a database size up to 524 PB, but its only limits on memory and processor sizes are the maximums set by your operating system. To support higher availability, this edition supports up to 8 secondary replicas, with up to two synchronous secondary replicas, in an availability group, online page and file restore, online indexing, fast recovery, mirrored backups, and the ability to hot add memory and CPU. For greater performance, Enterprise edition supports in-memory OLTP, table and index partitioning, data compression, Resource Governor, parallelism for partitioned tables, multiple file stream containers, and delayed durability, among other features. Enterprise edition includes many security features not found in Standard edition. In particular, Always Encrypted protects data at rest and in motion. Additional security features exclusive to Enterprise edition include more finely-grained auditing, transparent data encryption, and extensible key management. Features supporting data warehouse operations found only in Enterprise edition include change data capture, star join query optimizations, and parallel query processing on partitioned indexes and tables.
  • Developer This edition is for developers that create, test, and demonstrate applications using any of the data platform components available in Enterprise edition. However, the Developer edition cannot be used in a production environment.
  • Evaluation This edition is a free trial version of SQL Server 2016. You can use this for up to 180 days that you can use to explore all of the features available in Enterprise Edition before making a purchasing decision.

Database tiers:

  • Basic This service tier has a maximum database size of 2 GB and performance level of 5 DTUs. You use this option when you need a small database for an application or website with relatively few concurrent requests. The benchmark transaction rate is 16,600 transactions per hour.
  • Standard This service tier has a maximum database size of 250 GB and performance levels ranging from 10 to 100 DTUs. You can use this option when a database needs to support multiple applications and multiple concurrent requests for workgroup and web applications. With 50 DTUs, the benchmark transaction rate is 2,570 transactions per minute.
  • Premium This service tier has a maximum database size of 1 TB and performance levels ranging from 125 to 4,000 DTUs. You use this option for enterprise-level database requirements. With 1,000 DTUs, the benchmark transaction rate is 735 transactions per second.
DECLARE @TableName VARCHAR(20) = NULL
SELECT TableName = OBJECT_NAME(ID.object_id),
FullyQualifiedObjectName = ID.statement ,
EqualityColumns = ID.equality_columns ,
InEqualityColumns = ID.inequality_columns,
IncludedColumns = ID.included_columns,
UniqueCompiles = GS.unique_compiles,
UserSeeks = GS.user_seeks ,
UserScans = GS.user_scans ,
LastUserSeekTime = GS.last_user_seek ,
LastUserScanTime = GS.last_user_scan,
AvgTotalUserCost = GS.avg_total_user_cost , -- Average cost of the user queries that could be reduced by the index in the group.
AvgUserImpact = GS.avg_user_impact , -- The value means that the query cost would on average drop by this percentage if this missing index group was implemented.
SystemSeeks = GS.system_seeks ,
SystemScans = GS.system_scans,
LastSystemSeekTime = GS.last_system_seek ,
LastSystemScanTime = GS.last_system_scan,
AvgTotalSystemCost = GS.avg_total_system_cost ,
AvgSystemImpact = GS.avg_system_impact, -- Average percentage benefit that system queries could experience if this missing index group was implemented.
IndexAdvantage = GS.user_seeks * GS.avg_total_user_cost * (GS.avg_user_impact * 0.01),
ProposedIndex = 'CREATE INDEX [IX_' + OBJECT_NAME(ID.[object_id], ID.[database_id]) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(ID.[equality_columns], ''), ', ', '_'), '[', ''), ']', '') + CASE
WHEN ID.[equality_columns] IS NOT NULL
AND ID.[inequality_columns] IS NOT NULL
THEN '_'
ELSE ''
END + REPLACE(REPLACE(REPLACE(ISNULL(ID.[inequality_columns], ''), ', ', '_'), '[', ''), ']', '') + '_' + LEFT(CAST(NEWID() AS [nvarchar](64)), 5) + ']' + ' ON ' + ID.[statement] + ' (' + ISNULL(ID.[equality_columns], '') + CASE
WHEN ID.[equality_columns] IS NOT NULL
AND ID.[inequality_columns] IS NOT NULL
THEN ','
ELSE ''
END + ISNULL(ID.[inequality_columns], '') + ')' + ISNULL(' INCLUDE (' + ID.[included_columns] + ')', '') ,
CollectionDate = CAST(CURRENT_TIMESTAMP AS [smalldatetime])
FROM sys.dm_db_missing_index_group_stats GS
INNER JOIN [sys].[dm_db_missing_index_groups] IG
ON GS.[group_handle] = IG.[index_group_handle]
INNER JOIN [sys].[dm_db_missing_index_details] ID
ON IG.[index_handle] = ID.[index_handle]
WHERE ID.database_id = DB_ID() AND
(OBJECT_NAME(ID.object_id) = @TableName OR @TableName IS NULL)
ORDER BY [TableName], [IndexAdvantage] DESC
OPTION (FORCE ORDER)
DECLARE @TableName VARCHAR(20) = NULL
SELECT [SchemaName] = SCH.name,
[TableName] = TBL.name,
[IndexName] = INX.name,
[KeyColumnList] = STUFF(( SELECT ', ' + CDC.name + ' ' + CASE WHEN IDC.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END
FROM sys.tables AS T
INNER JOIN sys.indexes IDX
ON T.object_id = IDX.object_id
INNER JOIN sys.index_columns IDC
ON IDX.object_id = IDC.object_id AND
IDX.index_id = IDC.index_id
INNER JOIN sys.columns CDC
ON T.object_id = CDC.object_id AND
IDC.column_id = CDC.column_id
WHERE IDX.object_id = INX.object_id AND
IDX.index_id = INX.index_id AND
IDC.is_included_column = 0
ORDER BY IDC.key_ordinal
FOR XML PATH('')), 1, 2, ''),
[IncludeColumnList] = STUFF(( SELECT ', ' + CDC.name
FROM sys.tables AS T
INNER JOIN sys.indexes IDX
ON T.object_id = IDX.object_id
INNER JOIN sys.index_columns IDC
ON IDX.object_id = IDC.object_id AND
IDX.index_id = IDC.index_id
INNER JOIN sys.columns CDC
ON T.object_id = CDC.object_id AND
IDC.column_id = CDC.column_id
WHERE IDX.object_id = INX.object_id AND
IDX.index_id = INX.index_id AND
IDC.is_included_column = 1
ORDER BY IDC.key_ordinal
FOR XML PATH('')), 1, 2, ''),
[IsDisabled] = INX.is_disabled,
[IsUnique] = INX.is_unique
FROM sys.indexes INX
INNER JOIN sys.tables TBL
ON TBL.object_id = INX.object_id
INNER JOIN sys.schemas SCH
ON SCH.schema_id = TBL.schema_id
WHERE TBL.is_ms_shipped = 0 AND
(TBL.name = @TableName OR @TableName IS NULL) AND
INX.type_desc IN ('NONCLUSTERED', 'CLUSTERED')
OPTION (FORCE ORDER)

sys.dm_db_index_usage_stats

Returns counts of different types of index operations and the time each type of operation was last performed.

Column name Data type Description
database_id smallint ID of the database on which the table or view is defined.
object_id int ID of the table or view on which the index is defined
index_id int ID of the index.
user_seeks bigint Number of seeks by user queries.
user_scans bigint Number of scans by user queries that did not use 'seek' predicate.
user_lookups bigint Number of bookmark lookups by user queries.
user_updates bigint Number of updates by user queries. This includes Insert, Delete, and Updates representing number of operations done not the actual rows affected. For example, if you delete 1000 rows in one statement, this count increments by 1
last_user_seek datetime
last_user_scan datetime Time of last user scan.
last_user_lookup datetime Time of last user lookup.
last_user_update datetime Time of last user update.
system_seeks bigint Number of seeks by system queries.
system_scans bigint Number of scans by system queries.
system_lookups bigint Number of lookups by system queries.
system_updates bigint Number of updates by system queries.
last_system_seek datetime Time of last system seek.
last_system_scan datetime Time of last system scan.
last_system_lookup datetime Time of last system lookup.
last_system_update datetime Time of last system update.
pdw_node_id int Applies to: Azure SQL Data Warehouse, Parallel Data Warehouse

The identifier for the node that this distribution is on.

sys.dm_db_missing_index_group_stats

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment