Thursday, June 30, 2022

assisted index creation

SQL Server offers a lot of information on performance tuning, but it’s not always easy to find. One such area is finding missing indexes. sys.dm_db_missing_index_groups, sys.dm_db_missing_index_details and sys.dm_db_missing_index_group_stats are DMVs that offer details on indexes, the query optimizer would have used if they were available. The first offers information on missing indexes, the second offers us more details about those missing indexes and the last helps us identify the potential impact those indexes could make and helps us filter for meaningful suggestions. In my case, I defined (stat.avg_user_impact * (stat.user_seeks + stat.user_scans)) > 1000 as the minimum threshold, to avoid too much noise.

In my admin database, I set up the following view:

USE [Admin] 

GO

 

SET ANSI_NULLS ON

GO

 

SET QUOTED_IDENTIFIER ON

GO

 

CREATE VIEW [dbo].[suggestedIndex]

AS

SELECT DISTINCT

      'USE [' + db.name + ']' + CHAR(13)+CHAR(10)

    + 'GO' + CHAR(13)+CHAR(10)

    + 'CREATE INDEX [nci_' + OBJECT_NAME(det.OBJECT_ID,det.database_id) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(det.equality_columns,''),', ','_'),'[',''),']','')

    +  CASE

       WHEN det.equality_columns IS NOT NULL AND det.inequality_columns IS NOT NULL

       THEN '_'

       ELSE ''

       END + REPLACE(REPLACE(REPLACE(ISNULL(det.inequality_columns,''),', ','_'),'[',''),']','') + ']' + CHAR(13)+CHAR(10)

    + 'ON ' + det.statement + ' (' + ISNULL (det.equality_columns,'')

    +  CASE

       WHEN det.equality_columns IS NOT NULL AND det.inequality_columns IS NOT NULL

       THEN ','

       ELSE ''

       END + ISNULL (det.inequality_columns, '') + ')' + CHAR(13)+CHAR(10)

    +  ISNULL ('INCLUDE (' + det.included_columns + ')' + CHAR(13)+CHAR(10), '')

    +  CHAR(13)+CHAR(10AS Statement

 FROM master.sys.dm_db_missing_index_groups mi

 JOIN master.sys.dm_db_missing_index_group_stats stat

   ON stat.group_handle = mi.index_group_handle

 JOIN master.sys.dm_db_missing_index_details det

   ON mi.index_handle = det.index_handle

 JOIN master.sys.databases db

   ON det.database_id = db.database_id

WHERE (stat.avg_user_impact * (stat.user_seeks + stat.user_scans)) > 1000

to identify suggested indexes.

I then use the following lines of PowerShell

$ind = Invoke-Sqlcmd -Query "SELECT * FROM suggestedIndex" -ServerInstance $SQLserver -Database Admin

foreach($i in $ind){Send-MailMessage -From $UserName -Subject SuggestedIndex -To "me@mail.com" -Credential $cred -SmtpServer "smtp.mail.com" -UseSsl -Body $i.statement}

to send a create script for each index to myself. Obviously we can’t just blindly create all suggested indexes and have to apply some common sense, but I find it helpful to identify potential areas for improvement.

No comments:

Post a Comment

Replicate a database to Azure SQL Managed Instance – MI Link

MI Link  is a new feature connecting  SQL Server  hosted locally or on Azure VM with  Azure SQL Managed Instance. MI Link leverag...