1616ALTER PROCEDURE
1717 dbo .sp_IndexCleanup
1818(
19- @database_name sysname = NULL ,
20- @schema_name sysname = NULL ,
21- @table_name sysname = NULL ,
22- @min_reads bigint = 0 ,
23- @min_writes bigint = 0 ,
24- @min_size_gb decimal (10 ,2 ) = 0 ,
25- @min_rows bigint = 0 ,
26- @dedupe_only bit = 0 , /* only perform deduplication, don't mark unused indexes for removal*/
27- @get_all_databases bit = 0 , /* looks for all accessible user databases and returns combined results*/
19+ @database_name sysname = NULL , /* focus on a single database */
20+ @schema_name sysname = NULL , /* use when focusing on a single table, does not filter to a single schema */
21+ @table_name sysname = NULL , /* use when focusing on a single table */
22+ @min_reads bigint = 0 , /* only look at indexes with a minimum number of reads */
23+ @min_writes bigint = 0 , /* only look at indexes with a minimum number of writes */
24+ @min_size_gb decimal (10 ,2 ) = 0 , /* only look at indexes with a minimum size */
25+ @min_rows bigint = 0 , /* only look at indexes with a minimum number of rows */
26+ @dedupe_only bit = ' false' , /* only perform deduplication, don't mark unused indexes for removal*/
27+ @get_all_databases bit = ' false' , /* looks for all accessible user databases and returns combined results*/
2828 @include_databases nvarchar (max ) = NULL , /* comma-separated list of databases to include (only when @get_all_databases = 1)*/
2929 @exclude_databases nvarchar (max ) = NULL , /* comma-separated list of databases to exclude (only when @get_all_databases = 1)*/
30- @help bit = ' false' ,
31- @debug bit = ' false' ,
32- @version varchar (20 ) = NULL OUTPUT ,
33- @version_date datetime = NULL OUTPUT
30+ @help bit = ' false' , /* learn about the procedure and parameters */
31+ @debug bit = ' false' , /* print dynamic sql, show temp table contents */
32+ @version varchar (20 ) = NULL OUTPUT , /* script version number */
33+ @version_date datetime = NULL OUTPUT /* script version date */
3434)
3535WITH RECOMPILE
3636AS
3737BEGIN
3838SET NOCOUNT ON ;
39-
4039BEGIN TRY
41- /* Check for SQL Server 2012 (11.0) or later for FORMAT and CONCAT functions*/
40+ SELECT
41+ @version = ' 1.4' ,
42+ @version_date = ' 20250401' ;
4243
4344 IF
4445 /* Check SQL Server 2012+ for FORMAT and CONCAT functions */
@@ -67,10 +68,6 @@ BEGIN TRY
6768 RETURN ;
6869 END ;
6970
70- SELECT
71- @version = ' 1.4' ,
72- @version_date = ' 20250401' ;
73-
7471 /*
7572 Help section, for help.
7673 Will become more helpful when out of beta.
@@ -90,7 +87,10 @@ BEGIN TRY
9087 help = N ' always validate all changes against a non-production environment!'
9188 UNION ALL
9289 SELECT
93- help = N ' please test carefully.' ;
90+ help = N ' please test carefully.'
91+ UNION ALL
92+ SELECT
93+ help = N ' brought to you by erikdarling.com / code.erikdarling.com' ;
9494
9595 /*
9696 Parameters
@@ -285,22 +285,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
285285 END ;
286286
287287 /* Auto-enable dedupe_only mode if server uptime is low */
288- IF CONVERT (integer , @uptime_days) < 7 AND @dedupe_only = 0
288+ IF CONVERT (integer , @uptime_days) <= 7 AND @dedupe_only = 0
289289 BEGIN
290290 IF @debug = 1
291291 BEGIN
292292 RAISERROR (' Server uptime is less than 7 days. Automatically enabling @dedupe_only mode.' , 0 , 1 ) WITH NOWAIT ;
293293 END ;
294294
295- SELECT @dedupe_only = 1 ;
295+ SET @dedupe_only = 1 ;
296296 END ;
297297
298298 /*
299299 Initial checks for object validity
300300 */
301301 IF @debug = 1
302302 BEGIN
303- RAISERROR (' Checking paramaters ...' , 0 , 0 ) WITH NOWAIT ;
303+ RAISERROR (' Checking parameters ...' , 0 , 0 ) WITH NOWAIT ;
304304 END ;
305305
306306 IF @schema_name IS NULL
@@ -311,8 +311,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
311311 RAISERROR (' Parameter @schema_name cannot be NULL when specifying a table, defaulting to dbo' , 10 , 1 ) WITH NOWAIT ;
312312 END ;
313313
314- SELECT
315- @schema_name = N ' dbo' ;
314+ SET @schema_name = N ' dbo' ;
316315 END ;
317316
318317 IF @min_reads < 0
@@ -591,7 +590,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
591590 CREATE TABLE
592591 #index_reporting_stats
593592 (
594- summary_level varchar (20 ) NOT NULL , /* 'DATABASE', 'TABLE', 'INDEX', 'SUMMARY' */
593+ summary_level varchar (20 ) NOT NULL , /* 'DATABASE', 'TABLE', 'INDEX', 'SUMMARY' */
595594 database_name sysname NULL ,
596595 schema_name sysname NULL ,
597596 table_name sysname NULL ,
@@ -864,8 +863,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
864863 N ' rdsadmin'
865864 )
866865 BEGIN
867- SELECT
868- @database_name = DB_NAME ();
866+ SET @database_name = DB_NAME ();
869867 END ;
870868
871869 /* Single database mode */
@@ -892,7 +890,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
892890 /* Get the database_id for backwards compatibility */
893891 SELECT
894892 @current_database_id = d .database_id
895- FROM #databases AS d;
893+ FROM #databases AS d
894+ OPTION (RECOMPILE );
896895 END ;
897896 END
898897 ELSE
@@ -1128,7 +1127,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11281127 )' ;
11291128 END ;
11301129
1131-
11321130 IF @object_id IS NOT NULL
11331131 BEGIN
11341132 IF @debug = 1
@@ -2246,13 +2244,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22462244 (
22472245 SELECT
22482246 1 / 0
2249- FROM #index_details AS id
2247+ FROM #index_details AS id
22502248 WHERE id .index_id = #index_analysis .index_id
22512249 AND id .object_id = #index_analysis .object_id
22522250 AND id .user_scans > 0
22532251 ) THEN 100 ELSE 0
2254- END
2255- OPTION (RECOMPILE ); /* Indexes with scans get some priority */
2252+ END /* Indexes with scans get some priority */
2253+ OPTION (RECOMPILE );
22562254
22572255 IF @debug = 1
22582256 BEGIN
@@ -2291,8 +2289,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22912289 AND id .is_unique_constraint = 0 /* Don't disable unique constraints */
22922290 AND id .is_eligible_for_dedupe = 1 /* Only eligible indexes */
22932291 )
2294- AND #index_analysis .index_id <> 1
2295- OPTION (RECOMPILE ); /* Don't disable clustered indexes */
2292+ AND #index_analysis .index_id <> 1 /* Don't disable clustered indexes */
2293+ OPTION (RECOMPILE );
22962294 END ;
22972295
22982296 IF @debug = 1
@@ -2358,7 +2356,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23582356 AND id2_uc .index_id = ia2 .index_id
23592357 AND id2_uc .is_unique_constraint = 1
23602358 )
2361- AND EXISTS
2359+ AND EXISTS
23622360 (
23632361 SELECT
23642362 1 / 0
@@ -2670,7 +2668,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26702668 CASE
26712669 /* If both have includes, combine them without duplicates */
26722670 WHEN kss .superset_includes IS NOT NULL
2673- AND kss .subset_includes IS NOT NULL
2671+ AND kss .subset_includes IS NOT NULL
26742672 THEN
26752673 /* Create combined includes using XML method that works with all SQL Server versions */
26762674 (
@@ -2746,7 +2744,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27462744 UPDATE
27472745 ia2
27482746 SET
2749- ia2 .superseded_by = N ' Supersedes ' + ia1 .index_name
2747+ ia2 .superseded_by =
2748+ N ' Supersedes ' +
2749+ ia1 .index_name
27502750 FROM #index_analysis AS ia1
27512751 JOIN #index_analysis AS ia2
27522752 ON ia1 .database_id = ia2 .database_id
@@ -2782,7 +2782,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27822782 END
27832783 FROM #index_analysis AS ia1
27842784 WHERE ia1 .consolidation_rule IS NULL /* Not already processed */
2785- AND ia1 .action IS NULL /* Not already processed by earlier rules */
2785+ AND ia1 .action IS NULL /* Not already processed by earlier rules */
27862786 AND EXISTS
27872787 (
27882788 /* Find nonclustered indexes */
@@ -3676,7 +3676,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36763676 /* Sort duplicate/subset indexes first (20), then unused indexes last (25) */
36773677 sort_order =
36783678 CASE
3679- WHEN ia .consolidation_rule LIKE ' Unused Index%' THEN 25
3679+ WHEN ia .consolidation_rule LIKE ' Unused Index%'
3680+ THEN 25
36803681 ELSE 20
36813682 END ,
36823683 ia .database_name ,
@@ -3959,16 +3960,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39593960 OPTION (RECOMPILE );
39603961
39613962 /* If any clustered indexes were added, mark them as KEEP */
3962- UPDATE #index_analysis
3963- SET action = N ' KEEP'
3964- WHERE index_id = 1 /* Clustered indexes */
3965- AND action IS NULL ;
3963+ UPDATE
3964+ #index_analysis
3965+ SET
3966+ #index_analysis .action = N ' KEEP'
3967+ WHERE #index_analysis .index_id = 1 /* Clustered indexes */
3968+ AND #index_analysis .action IS NULL ;
39663969
39673970 /* Update index priority for clustered indexes to ensure they're not chosen for deduplication */
3968- UPDATE #index_analysis
3969- SET index_priority = 1000 /* Maximum priority */
3970- WHERE index_id = 1 /* Clustered indexes */
3971- AND index_priority IS NULL ;
3971+ UPDATE
3972+ #index_analysis
3973+ SET
3974+ #index_analysis .index_priority = 1000 /* Maximum priority */
3975+ WHERE #index_analysis .index_id = 1 /* Clustered indexes */
3976+ AND #index_analysis .index_priority IS NULL ;
39723977
39733978 IF @debug = 1
39743979 BEGIN
@@ -4461,7 +4466,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44614466 script_type =
44624467 CASE
44634468 /* Add compression status to script_type */
4464- WHEN ce .can_compress = 1 THEN ' KEPT - NEEDS COMPRESSION'
4469+ WHEN ce .can_compress = 1
4470+ THEN ' KEPT - NEEDS COMPRESSION'
44654471 ELSE ' KEPT'
44664472 END ,
44674473 ia .consolidation_rule ,
@@ -4849,7 +4855,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48494855 total_min_savings_gb =
48504856 (
48514857 SELECT
4852- SUM (
4858+ SUM
4859+ (
48534860 CASE
48544861 WHEN subia .action = N ' DISABLE'
48554862 THEN subps .total_space_gb
@@ -4874,7 +4881,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48744881 total_max_savings_gb =
48754882 (
48764883 SELECT
4877- SUM (
4884+ SUM
4885+ (
48784886 CASE
48794887 WHEN subia .action = N ' DISABLE'
48804888 THEN subps .total_space_gb
@@ -5097,7 +5105,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50975105 total_min_savings_gb =
50985106 (
50995107 SELECT
5100- SUM (
5108+ SUM
5109+ (
51015110 CASE
51025111 WHEN subia .action = N ' DISABLE'
51035112 THEN subps .total_space_gb
@@ -5124,7 +5133,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51245133 total_max_savings_gb =
51255134 (
51265135 SELECT
5127- SUM (
5136+ SUM
5137+ (
51285138 CASE
51295139 WHEN subia .action = N ' DISABLE'
51305140 THEN subps .total_space_gb
@@ -5302,13 +5312,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53025312 ROW_NUMBER () OVER
53035313 (
53045314 PARTITION BY
5305- database_name ,
5306- schema_name ,
5307- table_name,
5308- index_name,
5315+ irs . database_name ,
5316+ irs . schema_name ,
5317+ irs . table_name ,
5318+ irs . index_name ,
53095319 irs .script_type
53105320 ORDER BY
5311- result_type DESC /* Prefer non-NULL result types */
5321+ irs . result_type DESC /* Prefer non-NULL result types */
53125322 ) AS rn
53135323 FROM #index_cleanup_results AS irs
53145324 ) AS ir
@@ -5537,7 +5547,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55375547 WHEN ISNULL (irs .unused_indexes , 0 ) > 0
55385548 THEN FORMAT
55395549 (
5540- CONVERT (decimal (38 ,2 ),
5550+ CONVERT
5551+ (
5552+ decimal (38 ,2 ),
55415553 ISNULL
55425554 (
55435555 irs .user_updates /
@@ -5609,7 +5621,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56095621 THEN
56105622 FORMAT
56115623 (
5612- CONVERT (decimal (38 ,2 ),
5624+ CONVERT
5625+ (
5626+ decimal (38 ,2 ),
56135627 ISNULL
56145628 (
56155629 (irs .row_lock_wait_count + irs .page_lock_wait_count ) /
@@ -5695,7 +5709,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56955709 THEN
56965710 FORMAT
56975711 (
5698- CONVERT (decimal (38 ,2 ),
5712+ CONVERT
5713+ (
5714+ decimal (38 ,2 ),
56995715 ISNULL
57005716 (
57015717 (irs .page_latch_wait_count + irs .page_io_latch_wait_count ) /
0 commit comments