Notes to myself – Indexes

SQL PM at Microsoft Ignite

-- Script to generate SQL commands for disabling unused or less used indexes
USE [pwLegalOffice]; -- Change this to your database name
GO
DECLARE @DisableCommands NVARCHAR(MAX);
SET @DisableCommands = '';
WITH IndexUsageStats AS (
SELECT
OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
SUM(user_seeks + user_scans + user_lookups) AS TotalReads,
SUM(user_updates) AS TotalWrites,
i.index_id,
i.OBJECT_ID AS TableObjectId
FROM
sys.indexes AS i
INNER JOIN
sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id
WHERE
OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1
AND s.database_id = DB_ID() -- Ensure we're only looking at the current database
GROUP BY
i.OBJECT_ID, i.name, i.index_id
),
IndexPhysicalStats AS (
SELECT
OBJECT_NAME(OBJECT_ID) AS TableName,
index_id,
SUM(row_count) AS [RowCount],
SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB
FROM
sys.dm_db_partition_stats
GROUP BY
OBJECT_ID, index_id
),
UnusedIndexes AS (
SELECT
u.TableName,
u.IndexName
FROM
IndexUsageStats AS u
LEFT JOIN
IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id
WHERE
u.TotalReads = 0 -- Indexes with zero reads
OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads
)
SELECT
@DisableCommands = @DisableCommands + 'ALTER INDEX [' + IndexName + '] ON [' + TableName + '] DISABLE;' + CHAR(13)
FROM
UnusedIndexes;
-- Print out the commands to disable indexes
PRINT @DisableCommands;
-- Execute the command
--Exec @DisableCommands;
-- Script to generate SQL commands for disabling unused or less used indexes USE [pwLegalOffice]; -- Change this to your database name GO DECLARE @DisableCommands NVARCHAR(MAX); SET @DisableCommands = ''; WITH IndexUsageStats AS ( SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName, i.name AS IndexName, SUM(user_seeks + user_scans + user_lookups) AS TotalReads, SUM(user_updates) AS TotalWrites, i.index_id, i.OBJECT_ID AS TableObjectId FROM sys.indexes AS i INNER JOIN sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id WHERE OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1 AND s.database_id = DB_ID() -- Ensure we're only looking at the current database GROUP BY i.OBJECT_ID, i.name, i.index_id ), IndexPhysicalStats AS ( SELECT OBJECT_NAME(OBJECT_ID) AS TableName, index_id, SUM(row_count) AS [RowCount], SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB FROM sys.dm_db_partition_stats GROUP BY OBJECT_ID, index_id ), UnusedIndexes AS ( SELECT u.TableName, u.IndexName FROM IndexUsageStats AS u LEFT JOIN IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id WHERE u.TotalReads = 0 -- Indexes with zero reads OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads ) SELECT @DisableCommands = @DisableCommands + 'ALTER INDEX [' + IndexName + '] ON [' + TableName + '] DISABLE;' + CHAR(13) FROM UnusedIndexes; -- Print out the commands to disable indexes PRINT @DisableCommands; -- Execute the command --Exec @DisableCommands;
-- Script to generate SQL commands for disabling unused or less used indexes
USE [pwLegalOffice]; -- Change this to your database name
GO

DECLARE @DisableCommands NVARCHAR(MAX);
SET @DisableCommands = '';

WITH IndexUsageStats AS (
    SELECT
        OBJECT_NAME(i.OBJECT_ID) AS TableName,
        i.name AS IndexName,
        SUM(user_seeks + user_scans + user_lookups) AS TotalReads,
        SUM(user_updates) AS TotalWrites,
        i.index_id,
        i.OBJECT_ID AS TableObjectId
    FROM
        sys.indexes AS i
    INNER JOIN
        sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id
    WHERE
        OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1
        AND s.database_id = DB_ID() -- Ensure we're only looking at the current database
    GROUP BY
        i.OBJECT_ID, i.name, i.index_id
),
IndexPhysicalStats AS (
    SELECT
        OBJECT_NAME(OBJECT_ID) AS TableName,
        index_id,
        SUM(row_count) AS [RowCount],
        SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB
    FROM
        sys.dm_db_partition_stats
    GROUP BY
        OBJECT_ID, index_id
),
UnusedIndexes AS (
    SELECT
        u.TableName,
        u.IndexName
    FROM
        IndexUsageStats AS u
    LEFT JOIN
        IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id
    WHERE
        u.TotalReads = 0 -- Indexes with zero reads
        OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads
)
SELECT
    @DisableCommands = @DisableCommands + 'ALTER INDEX [' + IndexName + '] ON [' + TableName + '] DISABLE;' + CHAR(13)
FROM
    UnusedIndexes;

-- Print out the commands to disable indexes
PRINT @DisableCommands;

-- Execute the command
--Exec @DisableCommands;


-- Index fragmentation information
SELECT Tab.name Table_Name
,IX.name Index_Name
,IX.type_desc Index_Type
,Col.name Index_Column_Name
,IXC.is_included_column Is_Included_Column
,IX.fill_factor
,IX.is_disabled
,IX.is_primary_key
,IX.is_unique
FROM sys.indexes IX
INNER JOIN sys.index_columns IXC ON IX.object_id = IXC.object_id AND IX.index_id = IXC.index_id
INNER JOIN sys.columns Col ON IX.object_id = Col.object_id AND IXC.column_id = Col.column_id
INNER JOIN sys.tables Tab ON IX.object_id = Tab.object_id
-- Index fragmentation information SELECT Tab.name Table_Name ,IX.name Index_Name ,IX.type_desc Index_Type ,Col.name Index_Column_Name ,IXC.is_included_column Is_Included_Column ,IX.fill_factor ,IX.is_disabled ,IX.is_primary_key ,IX.is_unique FROM sys.indexes IX INNER JOIN sys.index_columns IXC ON IX.object_id = IXC.object_id AND IX.index_id = IXC.index_id INNER JOIN sys.columns Col ON IX.object_id = Col.object_id AND IXC.column_id = Col.column_id INNER JOIN sys.tables Tab ON IX.object_id = Tab.object_id
-- Index fragmentation information
SELECT  Tab.name  Table_Name 
			 ,IX.name  Index_Name
			 ,IX.type_desc Index_Type
			 ,Col.name  Index_Column_Name
			 ,IXC.is_included_column Is_Included_Column
			 ,IX.fill_factor 
			 ,IX.is_disabled
			 ,IX.is_primary_key
			 ,IX.is_unique
			 		  
           FROM  sys.indexes IX 
           INNER JOIN sys.index_columns IXC  ON  IX.object_id   =   IXC.object_id AND  IX.index_id  =  IXC.index_id  
           INNER JOIN sys.columns Col   ON  IX.object_id   =   Col.object_id  AND IXC.column_id  =   Col.column_id     
           INNER JOIN sys.tables Tab      ON  IX.object_id = Tab.object_id
-- Index structure information and statistics
-- List all index in a sigle table
sp_helpindex '[dbo].[Contact]'
-- Update statistics in a single table using fullscan
-- ( for more critical and most updated tables )
UPDATE STATISTICS tableName indexName WITH FULLSCAN;
-- Update statistics in a single table
UPDATE STATISTICS [dbo].[Contact];
-- Update statistics for all tables in a database
EXEC sp_updatestats;
-- Set automatically update statistics as needed
ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS ON;
-- Set automatically update statistics as needed
-- (This allows queries to use existing statistics while new statistics are being generated)
ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS_ASYNC ON;
-- Index structure information and statistics -- List all index in a sigle table sp_helpindex '[dbo].[Contact]' -- Update statistics in a single table using fullscan -- ( for more critical and most updated tables ) UPDATE STATISTICS tableName indexName WITH FULLSCAN; -- Update statistics in a single table UPDATE STATISTICS [dbo].[Contact]; -- Update statistics for all tables in a database EXEC sp_updatestats; -- Set automatically update statistics as needed ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS ON; -- Set automatically update statistics as needed -- (This allows queries to use existing statistics while new statistics are being generated) ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS_ASYNC ON;
-- Index structure information and statistics 

-- List all index in a sigle table
sp_helpindex '[dbo].[Contact]'

-- Update statistics in a single table using fullscan 
-- ( for more critical and most updated tables )
UPDATE STATISTICS tableName indexName WITH FULLSCAN;

-- Update statistics in a single table
UPDATE STATISTICS [dbo].[Contact];

-- Update statistics for all tables in a database
EXEC sp_updatestats;

-- Set automatically update statistics as needed
ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS ON;

-- Set automatically update statistics as needed 
-- (This allows queries to use existing statistics while new statistics are being generated) 
ALTER DATABASE [pwLegalOffice] SET AUTO_UPDATE_STATISTICS_ASYNC ON;

-- Index usage information
SELECT OBJECT_NAME(IX.OBJECT_ID) Table_Name
,IX.name AS Index_Name
,IX.type_desc Index_Type
,SUM(PS.[used_page_count]) * 8 IndexSizeKB
,IXUS.user_seeks AS NumOfSeeks
,IXUS.user_scans AS NumOfScans
,IXUS.user_lookups AS NumOfLookups
,IXUS.user_updates AS NumOfUpdates
,IXUS.last_user_seek AS LastSeek
,IXUS.last_user_scan AS LastScan
,IXUS.last_user_lookup AS LastLookup
,IXUS.last_user_update AS LastUpdate
FROM sys.indexes IX
INNER JOIN sys.dm_db_index_usage_stats IXUS ON IXUS.index_id = IX.index_id AND IXUS.OBJECT_ID = IX.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats PS on PS.object_id=IX.object_id
WHERE OBJECTPROPERTY(IX.OBJECT_ID,'IsUserTable') = 1
GROUP BY OBJECT_NAME(IX.OBJECT_ID) ,IX.name ,IX.type_desc ,IXUS.user_seeks ,IXUS.user_scans ,IXUS.user_lookups,IXUS.user_updates ,IXUS.last_user_seek ,IXUS.last_user_scan ,IXUS.last_user_lookup ,IXUS.last_user_update
-- Index usage information SELECT OBJECT_NAME(IX.OBJECT_ID) Table_Name ,IX.name AS Index_Name ,IX.type_desc Index_Type ,SUM(PS.[used_page_count]) * 8 IndexSizeKB ,IXUS.user_seeks AS NumOfSeeks ,IXUS.user_scans AS NumOfScans ,IXUS.user_lookups AS NumOfLookups ,IXUS.user_updates AS NumOfUpdates ,IXUS.last_user_seek AS LastSeek ,IXUS.last_user_scan AS LastScan ,IXUS.last_user_lookup AS LastLookup ,IXUS.last_user_update AS LastUpdate FROM sys.indexes IX INNER JOIN sys.dm_db_index_usage_stats IXUS ON IXUS.index_id = IX.index_id AND IXUS.OBJECT_ID = IX.OBJECT_ID INNER JOIN sys.dm_db_partition_stats PS on PS.object_id=IX.object_id WHERE OBJECTPROPERTY(IX.OBJECT_ID,'IsUserTable') = 1 GROUP BY OBJECT_NAME(IX.OBJECT_ID) ,IX.name ,IX.type_desc ,IXUS.user_seeks ,IXUS.user_scans ,IXUS.user_lookups,IXUS.user_updates ,IXUS.last_user_seek ,IXUS.last_user_scan ,IXUS.last_user_lookup ,IXUS.last_user_update
-- Index usage information
SELECT OBJECT_NAME(IX.OBJECT_ID) Table_Name
	   ,IX.name AS Index_Name
	   ,IX.type_desc Index_Type
	   ,SUM(PS.[used_page_count]) * 8 IndexSizeKB
	   ,IXUS.user_seeks AS NumOfSeeks
	   ,IXUS.user_scans AS NumOfScans
	   ,IXUS.user_lookups AS NumOfLookups
	   ,IXUS.user_updates AS NumOfUpdates
	   ,IXUS.last_user_seek AS LastSeek
	   ,IXUS.last_user_scan AS LastScan
	   ,IXUS.last_user_lookup AS LastLookup
	   ,IXUS.last_user_update AS LastUpdate
FROM sys.indexes IX
INNER JOIN sys.dm_db_index_usage_stats IXUS ON IXUS.index_id = IX.index_id AND IXUS.OBJECT_ID = IX.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats PS on PS.object_id=IX.object_id
WHERE OBJECTPROPERTY(IX.OBJECT_ID,'IsUserTable') = 1
GROUP BY OBJECT_NAME(IX.OBJECT_ID) ,IX.name ,IX.type_desc ,IXUS.user_seeks ,IXUS.user_scans ,IXUS.user_lookups,IXUS.user_updates ,IXUS.last_user_seek ,IXUS.last_user_scan ,IXUS.last_user_lookup ,IXUS.last_user_update
-- Script to find unused or less used indexes in all tables of a SQL Server Database
USE [pwLegalOffice]; -- Change this to your database name
GO
;WITH IndexUsageStats AS (
SELECT
OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
SUM(user_seeks + user_scans + user_lookups) AS TotalReads,
SUM(user_updates) AS TotalWrites,
i.index_id,
i.OBJECT_ID AS TableObjectId
FROM
sys.indexes AS i
INNER JOIN
sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id
WHERE
OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1
AND s.database_id = DB_ID() -- Ensure we're only looking at the current database
GROUP BY
i.OBJECT_ID, i.name, i.index_id
),
IndexPhysicalStats AS (
SELECT
OBJECT_NAME(OBJECT_ID) AS TableName,
index_id,
SUM(row_count) AS [RowCount],
SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB
FROM
sys.dm_db_partition_stats
GROUP BY
OBJECT_ID, index_id
)
SELECT
u.TableName,
u.IndexName,
u.TotalReads,
u.TotalWrites,
p.[RowCount],
p.IndexSizeKB
FROM
IndexUsageStats AS u
LEFT JOIN
IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id
WHERE
u.TotalReads = 0 -- Indexes with zero reads
OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads
ORDER BY
u.TableName,
u.IndexName;
-- Script to find unused or less used indexes in all tables of a SQL Server Database USE [pwLegalOffice]; -- Change this to your database name GO ;WITH IndexUsageStats AS ( SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName, i.name AS IndexName, SUM(user_seeks + user_scans + user_lookups) AS TotalReads, SUM(user_updates) AS TotalWrites, i.index_id, i.OBJECT_ID AS TableObjectId FROM sys.indexes AS i INNER JOIN sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id WHERE OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1 AND s.database_id = DB_ID() -- Ensure we're only looking at the current database GROUP BY i.OBJECT_ID, i.name, i.index_id ), IndexPhysicalStats AS ( SELECT OBJECT_NAME(OBJECT_ID) AS TableName, index_id, SUM(row_count) AS [RowCount], SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB FROM sys.dm_db_partition_stats GROUP BY OBJECT_ID, index_id ) SELECT u.TableName, u.IndexName, u.TotalReads, u.TotalWrites, p.[RowCount], p.IndexSizeKB FROM IndexUsageStats AS u LEFT JOIN IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id WHERE u.TotalReads = 0 -- Indexes with zero reads OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads ORDER BY u.TableName, u.IndexName;
-- Script to find unused or less used indexes in all tables of a SQL Server Database

USE [pwLegalOffice]; -- Change this to your database name
GO

;WITH IndexUsageStats AS (
    SELECT
        OBJECT_NAME(i.OBJECT_ID) AS TableName,
        i.name AS IndexName,
        SUM(user_seeks + user_scans + user_lookups) AS TotalReads,
        SUM(user_updates) AS TotalWrites,
        i.index_id,
        i.OBJECT_ID AS TableObjectId
    FROM
        sys.indexes AS i
    INNER JOIN
        sys.dm_db_index_usage_stats AS s ON i.OBJECT_ID = s.OBJECT_ID AND i.index_id = s.index_id
    WHERE
        OBJECTPROPERTY(i.OBJECT_ID, 'IsUserTable') = 1
        AND s.database_id = DB_ID() -- Ensure we're only looking at the current database
    GROUP BY
        i.OBJECT_ID, i.name, i.index_id
),
IndexPhysicalStats AS (
    SELECT
        OBJECT_NAME(OBJECT_ID) AS TableName,
        index_id,
        SUM(row_count) AS [RowCount],
        SUM(used_page_count) * 8 AS IndexSizeKB -- Convert pages to KB
    FROM
        sys.dm_db_partition_stats
    GROUP BY
        OBJECT_ID, index_id
)
SELECT
    u.TableName,
    u.IndexName,
    u.TotalReads,
    u.TotalWrites,
    p.[RowCount],
    p.IndexSizeKB
FROM
    IndexUsageStats AS u
LEFT JOIN
    IndexPhysicalStats AS p ON u.TableName = p.TableName AND u.index_id = p.index_id
WHERE
    u.TotalReads = 0 -- Indexes with zero reads
    OR u.TotalReads < u.TotalWrites -- Or, indexes with more writes than reads
ORDER BY
    u.TableName,
    u.IndexName;

Leave a Reply

Your email address will not be published.