The following DMV query retrieves the usage statistics for existing indexes. User Seeks – A high number indicates a well utilized index. User Scans – Number of times the index has been scanned. Could indicate improper ordering of the composite columns User Lookups – Indicates a different index was used for criteria and the actual data was looked up from this index for the select list User Updates – Number of times the index was updated with additional records [cc lang=”sql”] SELECT ObjectName = object_schema_name(idx.object_id) + ‘.’ + object_name(idx.object_id) ,IndexName = idx.name ,IndexType = CASE WHEN is_unique = 1 THEN ‘UNIQUE ‘ ELSE ” END + idx.type_desc ,User_Seeks = us.user_seeks ,User_Scans = us.user_scans ,User_Lookups = us.user_lookups ,User_Updates = us.user_updates FROM sys.indexes idx LEFT JOIN sys.dm_db_index_usage_stats us ON idx.object_id = us.object_id AND idx.index_id = us.index_id AND us.database_id = db_id() WHERE object_schema_name(idx.object_id) != ‘sys’ ORDER BY us.user_seeks + us.user_scans + us.user_lookups DESC [/cc]
Continue reading ...
This query will show the indexes that are missing ordered according to those having the most impact. It will also provide the create index script needed in order to help you create the index. [cc lang=”sql”] SELECT mid.statement ,migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,OBJECT_NAME(mid.Object_id), ‘CREATE INDEX [missing_index_’ + CONVERT (varchar, mig.index_group_handle) + ‘_’ + CONVERT (varchar, mid.index_handle) + ‘_’ + LEFT (PARSENAME(mid.statement, 1), 32) + ‘]’ + ‘ ON ‘ + mid.statement + ‘ (‘ + ISNULL (mid.equality_columns,”) + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ‘,’ ELSE ” END + ISNULL (mid.inequality_columns, ”) + ‘)’ + ISNULL (‘ INCLUDE (‘ + mid.included_columns + ‘)’, ”) AS create_index_statement, migs.*, mid.database_id, mid.[object_id] FROM sys.dm_db_missing_index_groups mig INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10 ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC [/cc] What you need to know about this script however is what it does not account for. It does not account for an index that should be clustered. One of the warning signs that an index should be clustered is when this query suggests to you an index that contains a lot of columns (or has a lot of include columns). It is suggesting that, because it does not want to do a bookmark lookup to get the columns it needs for the select list. In those cases, […]
Continue reading ...
One of the most common database performance issue most companies face is the improper choice of indexes or the lack of indexes. Most essential, is the clustered index. A well-chosen clustered index will save CPU, Memory, and IO. Choosing the clustered index for a table goes hand-in-hand with the writing of the queries for a table. It is best to design the queries and the index simultaneously to keep consistency. The majority of the time this is not an option. When we have not written the queries, the best way to understand the optimal clustered index is to study the queries that are run against the table. Once you understand the queries that run against a table, it is helpful to think of each of these queries broken down into three parts: The select list – Be on the lookout for the queries that return the most columns from the table. The join columns – The most common columns used to join other tables against the table. The where clause – The most common columns used to filter the result sets. Avoiding Fragmentation Before going into depth in choosing a clustered index we need to know what causes fragmentation. We ideally want to answer no to the following: Will the clustered value(s) be updated? Can new rows be inserted between already inserted clustered rows? The reason for answering no above is because we do not want fragmentation at the clustered level. The clustered index is like the foundation of a […]
Continue reading ...