4Jun/103
Index Interrogation for SQL Server 2008
I had previously posted an index interrogation script for SQL Server 2005. I've updated that script for 2008; namely, it includes filtered index definitions. For anyone interested:
Declare @objectID int = Object_ID('Sales.SalesOrderHeader'); With indexCTE(partition_scheme_name , partition_function_name , data_space_id) As ( Select sps.name , spf.name , sps.data_space_id From sys.partition_schemes As sps Join sys.partition_functions As spf On sps.function_id = spf.function_id ) Select st.name As 'table_name' , IsNull(ix.name, '') As 'index_name' , ix.object_id , ix.index_id , Cast( Case When ix.index_id = 1 Then 'clustered' When ix.index_id =0 Then 'heap' Else 'nonclustered' End + Case When ix.ignore_dup_key <> 0 Then ', ignore duplicate keys' Else '' End + Case When ix.is_unique <> 0 Then ', unique' Else '' End + Case When ix.is_primary_key <> 0 Then ', primary key' Else '' End As varchar(210) ) As 'index_description' , IsNull(Replace( Replace( Replace( ( Select c.name As 'columnName' From sys.index_columns As sic Join sys.columns As c On c.column_id = sic.column_id And c.object_id = sic.object_id Where sic.object_id = ix.object_id And sic.index_id = ix.index_id And is_included_column = 0 Order By sic.index_column_id For XML Raw) , '"/><row columnName="', ', ') , '<row columnName="', '') , '"/>', ''), '') As 'indexed_columns' , IsNull(Replace( Replace( Replace( ( Select c.name As 'columnName' From sys.index_columns As sic Join sys.columns As c On c.column_id = sic.column_id And c.object_id = sic.object_id Where sic.object_id = ix.object_id And sic.index_id = ix.index_id And is_included_column = 1 Order By sic.index_column_id For XML Raw) , '"/><row columnName="', ', ') , '<row columnName="', '') , '"/>', ''), '') As 'included_columns' , ix.filter_definition , IsNull(cte.partition_scheme_name, '') As 'partition_scheme_name' , Count(partition_number) As 'partition_count' , Sum(rows) As 'row_count' From sys.indexes As ix Join sys.partitions As sp On ix.object_id = sp.object_id And ix.index_id = sp.index_id Join sys.tables As st On ix.object_id = st.object_id Left Join indexCTE As cte On ix.data_space_id = cte.data_space_id Where ix.object_id = IsNull(@objectID, ix.object_id) Group By st.name , IsNull(ix.name, '') , ix.object_id , ix.index_id , Cast( Case When ix.index_id = 1 Then 'clustered' When ix.index_id =0 Then 'heap' Else 'nonclustered' End + Case When ix.ignore_dup_key <> 0 Then ', ignore duplicate keys' Else '' End + Case When ix.is_unique <> 0 Then ', unique' Else '' End + Case When ix.is_primary_key <> 0 Then ', primary key' Else '' End As varchar(210) ) , ix.filter_definition , IsNull(cte.partition_scheme_name, '') , IsNull(cte.partition_function_name, '') Order By table_name , index_id;
You may need to create some indexes to see this in AdventureWorks:
Create NonClustered Index IX_Sales_SalesOrderHeader_filtered_2005 On Sales.SalesOrderHeader(AccountNumber) Include (CustomerID, SalesPersonID) Where OrderDate >= '2005-01-01' And OrderDate < '2006-01-01';
table_name index_name object_id index_id index_description indexed_columns included_columns filter_definition partition_scheme_name partition_count row_count -------------------- ---------------------------------------- ----------- ----------- ----------------------------------- -------------------- ------------------------------ ------------------------------------------------------------ --------------------- --------------- -------------------- SalesOrderHeader PK_SalesOrderHeader_SalesOrderID 1010102639 1 clustered, unique, primary key SalesOrderID NULL 1 31465 SalesOrderHeader AK_SalesOrderHeader_rowguid 1010102639 2 nonclustered, unique rowguid NULL 1 31465 SalesOrderHeader AK_SalesOrderHeader_SalesOrderNumber 1010102639 3 nonclustered, unique SalesOrderNumber NULL 1 31465 SalesOrderHeader IX_SalesOrderHeader_CustomerID 1010102639 5 nonclustered CustomerID NULL 1 31465 SalesOrderHeader IX_SalesOrderHeader_SalesPersonID 1010102639 6 nonclustered SalesPersonID NULL 1 31465 SalesOrderHeader IX_Sales_SalesOrderHeader_filtered_2005 1010102639 13 nonclustered AccountNumber CustomerID, SalesPersonID ([OrderDate]>='2005-01-01' AND [OrderDate]<'2006-01-01') 1 1379
Tagged as: indexes, partitioning, script, T-SQL Scripts, tips, TSQL
Leave a comment
Categories
- Business Intelligence
- Internals
- Miscellaneous
- PASS
- Performance & Tuning
- Presentations
- SQL 2008
- SQL Tips
- Syndication
- T-SQL Scripts
Subscribe to my blog!
| Like what you see? Subscribe! |
![]() |
Around the Web
Recent Tweets
- @gregsohl yeah, that would be a nice feature. Did you find any products that do support field-level dependencies?
- @MladenPrajdic @atlantis_uk Thanks, Mladen, I'll be sure to check that out. :)
- I'm really lovin' @RedGate's #SQL Dependency Tracker. I can see it saving me a *lot* of time once I figure out what the heck I'm doing :)
Archives
- November 2011
- October 2011
- September 2011
- July 2011
- June 2011
- May 2011
- April 2011
- January 2011
- December 2010
- November 2010
- October 2010
- September 2010
- July 2010
- June 2010
- May 2010
- April 2010
- February 2010
- January 2010
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008



June 15th, 2010 - 20:31
It will be helpful if you can add Index Fragmentation column to show the average fragmentation percentage & size while interrogating those Indexes.
thanks
Jay
June 16th, 2010 - 07:50
Hi Jay. The current query above just uses meta data to return information about indexes. Because of that, it’s very fast and lightweight. Fragmentation information, on the other hand, would be a very expensive operation, as it examines the actual page data to determine the amount of fragmentation. I’d much prefer to keep the index information script lightweight, since I usually just want to see columns are part of the index, etc. If you’re looking for fragmentation information, you can query the sys.dm_db_index_physical_stats DMF or you can use my index defrag script here: http://sqlfool.com/2010/04/index-defrag-script-v4-0/
June 24th, 2010 - 07:02
Thanks Michelle! Another cool script. Sadly I have yet to find the script that gets the indexed views information, especially when we start hitting the include columns. One of these days I’ll have to sit down and write something.
Thanks again.