This post was last updated on March 16th, 2015 at 09:01 am

Sometimes a quick script is just what the doctor ordered.

I recently had the task of packaging up a database to ship it offsite. This database had some size to it, approximately 200GB with 6 tables. While looking at the tables, I noticed that though they were relatively narrow, each had ~22 million rows in them. In my environment this wasn’t wild or out of the ordinary, however, I did think that the disk space usage was a little out of whack given what I was seeing. So, I set out to see if I could make the database smaller so that it was easier to transport.

I discovered that each table had anywhere from 7-15 non-clustered indexes on them. As we know, a non-clustered index is a partial copy of the data, so it was extra bloat that we didn’t need. I knew those that would be consuming the data would pull in every table in its entirety, so I wasn’t overly concerned about them having index scans versus index seeks on the data.

Each table, however, did have a clustered index on it so I knew that I wanted to leave it in place. It was only the non-clustered indexes causing extra weight that I didn’t need. So I wrote a quick T-SQL script to help drop that weight. While this script isn’t overly fancy or complex, it turned out to be handy and gave me the ability to manually control dropping all of the non-clustered indexes in the database.

DISCLAIMER: Do not run code you find on the internet in your production environment without testing it very thoroughly. Period.

/*************************************************************** -- Author: John Morehouse -- Date: February 2015 -- T: @SQLRUS -- E: [email protected] -- B: http://landingzone.jmorehouse.com/sqlrus --THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. --IN OTHER WORDS: USE AT YOUR OWN RISK. --AUTHOR ASSUMES ZERO LIABILITY OR RESPONSIBILITY. --You may alter this code for your own purposes. --You may republish altered code as long as you give due credit. --Updated: --20150316: MorehouseJ: Added in join to sys.tables based off feedback from JohnW to account for FILESTREAM tables. Also removed ORDER BY for the KeyConstraintID column. ***************************************************************/ USE [AdventureWorks]; GO SELECT CASE WHEN kc.object_id IS NOT NULL THEN 'ALTER TABLE ' + QUOTENAME(ss.name) + '.' + QUOTENAME(so.name) + ' DROP CONSTRAINT ' + si.name + ';' ELSE 'DROP INDEX ' + si.name + ' ON ' + QUOTENAME(ss.name) + '.' + QUOTENAME(so.name) + ';' END as 'Drop Command' , si.object_id as 'Object ID' , si.name as 'Index Name' , si.index_id as 'Index ID' , si.type_desc as 'Index Type' , object_name(so.object_id) as 'Table Name' , si.is_unique , si.is_primary_key FROM sys.indexes si INNER JOIN sys.objects so ON si.object_id = so.object_ID INNER JOIN sys.schemas ss ON so.schema_ID = ss.schema_id LEFT JOIN sys.key_constraints kc on si.name = kc.name INNER JOIN sys.tables st ON si.object_id = st.object_ID WHERE si.object_id > 100 -- system objects AND si.type >= 2 -- anything not a clustered index AND so.is_ms_shipped = 0 -- ignore MS specific objects AND NOT EXISTS (SELECT name FROM sys.xml_indexes WHERE xml_index_type > 0 AND name = si.name) AND st.filestream_data_space_id IS NULL ORDER BY [Index Type] GO

It is worth noting that if the index was created from a PRIMARY KEY or UNIQUE constraint, it cannot be dropped using a simple DROP statement. You have to use the ‘ALTER TABLE … DROP CONSTRAINT’ method to drop the index. The script I have provided will handle that for you as well as handle XML indexes and spatial indexes.

For a given database, it generates the ‘DROP’ statements for all of the non-clustered indexes. It’s that simple. It also includes some additional meta-data, like the schema, about the index. Once the query is complete, all you have to do is just copy out the command in the first column, labeled ‘Drop Command’. Take that statement and paste it into another SSMS window and execute it as you wish. You can execute the entire thing or perform it line by line.

Of course, I’d be remiss if I didn’t say it again, please DO NOT execute that resulting command on a production database. That command could have severe impact to your production systems.

Yes, I could have probably written a PoSH script to do this work. Well, Ok. I could have asked my good friend Mike Fal (B|T) to write a PoSH script for me. He’s a wizard at it. Yes, I too could have written a cursor/loop to go do the work for me, but I didn’t want to. I like quick and dirty scripts such as this one. It allows me to do what I need to do with a relatively short amount of work. This script helped to get the database size down significantly (of course I had to shrink afterward *GASP*) and then it was much easier to transport once that weight was dropped. The consumers of the data were also very happy as this also helped them to save space on their servers

Enjoy!

© 2015, John Morehouse. All rights reserved.

Share this: Twitter

Facebook

LinkedIn

Print

Email



Like this: Like Loading...