SQL Server Tipp – Fehlende Indizes finden

Heute Morgen hat ein Kunde über Performance Probleme in einer Anwendung Bescheid gegeben. Der Anwendungsserver sieht gut aus (CPU/RAM/Plattenplatz), auf die DB komme ich auch und die Anwendung reagiert. Hmmmm….

„Vielleicht fehlen Indizes in der DB?“, dachte ich mir. „Kann man das irgendwo klicken?“ war die zweite Frage. „Im SQL Server kann man doch alles irgendwie abfragen, aber wie?“ war meine dritte Frage, mit der ich auf eine große Suchmaschine los bin.

Und siehe da, es gibt bei Microsoft was zu dem Thema unter https://technet.microsoft.com/en-us/library/ms345417(v=sql.105).aspx und ich habe von Basit A. Farooq (@BasitAali) einen Eintrag in seinem Blog gefunden: Find missing indexes using SQL Servers index related DMVs . Danke!

Das von Basit vorgestellte Skript tut einen guten Dienst beim Auffinden und sogar beim Erstellen von Indexskripts. Benutzt werden dabei die Dynamic Management Objects [sys].[dm_db_missing_index_group_stats][sys].[dm_db_missing_index_groups] und [sys].[dm_db_missing_index_details]:

SELECT CAST(SERVERPROPERTY('ServerName') AS [nvarchar](256)) AS [SQLServer]
 ,db.[database_id] AS [DatabaseID]
 ,db.[name] AS [DatabaseName]
 ,id.[object_id] AS [ObjectID]
 ,id.[statement] AS [FullyQualifiedObjectName]
 ,id.[equality_columns] AS [EqualityColumns]
 ,id.[inequality_columns] AS [InEqualityColumns]
 ,id.[included_columns] AS [IncludedColumns]
 ,gs.[unique_compiles] AS [UniqueCompiles]
 ,gs.[user_seeks] AS [UserSeeks]
 ,gs.[user_scans] AS [UserScans]
 ,gs.[last_user_seek] AS [LastUserSeekTime]
 ,gs.[last_user_scan] AS [LastUserScanTime]
 ,gs.[avg_total_user_cost] AS [AvgTotalUserCost]
 ,gs.[avg_user_impact] AS [AvgUserImpact]
 ,gs.[system_seeks] AS [SystemSeeks]
 ,gs.[system_scans] AS [SystemScans]
 ,gs.[last_system_seek] AS [LastSystemSeekTime]
 ,gs.[last_system_scan] AS [LastSystemScanTime]
 ,gs.[avg_total_system_cost] AS [AvgTotalSystemCost]
 ,gs.[avg_system_impact] AS [AvgSystemImpact]
 ,gs.[user_seeks] * gs.[avg_total_user_cost] * (gs.[avg_user_impact] * 0.01) AS [IndexAdvantage]
 ,'CREATE INDEX [Missing_IXNC_' + OBJECT_NAME(id.[object_id], db.[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] + ')', '') AS [ProposedIndex]
 ,CAST(CURRENT_TIMESTAMP AS [smalldatetime]) AS [CollectionDate]
FROM [sys].[dm_db_missing_index_group_stats] gs WITH (NOLOCK)
INNER JOIN [sys].[dm_db_missing_index_groups] ig WITH (NOLOCK)
 ON gs.[group_handle] = ig.[index_group_handle]
INNER JOIN [sys].[dm_db_missing_index_details] id WITH (NOLOCK)
 ON ig.[index_handle] = id.[index_handle]
INNER JOIN [sys].[databases] db WITH (NOLOCK)
 ON db.[database_id] = id.[database_id]
WHERE id.[database_id] > 4 -- Remove this to see for entire instance
ORDER BY [IndexAdvantage] DESC
OPTION (RECOMPILE);

Cooles Skript und nochmal Danke/Thanx Basit!

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s