top of page

Review Indexes On SQL Server

Part 1


In the realm of database management, the quest for efficiency and performance is never-ending. As the backbone of many enterprise solutions, SQL Server stands at the forefront of this crusade, offering a powerful platform where organized data retrieval is critical. However, in a world where data is incessantly growing and the need for rapid access is non-negotiable, the way SQL Server indexes are utilized can make or break application performance.

Review Indexes On SQL Server: Introduction

At its heart, an index accelerates the retrieval of database content by providing quick access to the rows that match a particular value. It's akin to the index section of a book, enabling you to jump straight to the desired section without flipping through every page. SQL Server indexing is vital for databases with large volumes of data, where the difference in milliseconds can be monumental.


SQL Server supports various types of indexes across different versions, with some differences in features and capabilities. Here are the major differences in index support across different versions:

SQL Server 2005:

  • Supports clustered, non-clustered, and unique indexes.

  • Filtered indexes were not introduced until SQL Server 2008.

  • Indexed views are supported but have limitations compared to later versions.

SQL Server 2008:

  • Introduces filtered indexes, which allow indexing on a subset of rows based on a filter condition.

  • Enhancements to indexed views, including the ability to create indexed views with OUTER JOINs.

SQL Server 2012:

  • Introduces columnstore indexes for optimizing analytical query performance on large datasets.

  • Enhancements to online index operations, allowing for more efficient index maintenance operations while the database remains online.

  • Supports the INCLUDE clause in non-clustered indexes to include additional columns in the index leaf level.

SQL Server 2014:

  • Introduces clustered columnstore indexes, which store data in a columnar format for improved compression and query performance.

  • Enhancements to non-clustered columnstore indexes, including support for updateable non-clustered columnstore indexes.

  • Introduces buffer pool extension, which allows SSDs to be used as an extension of the buffer pool for caching frequently accessed data, potentially improving index performance.

SQL Server 2016:

  • Introduces the ability to create temporal tables with system-versioning, allowing for easy tracking of data changes over time.

  • Introduces support for memory-optimized tables and indexes for improving performance of OLTP workloads.

SQL Server 2017:

  • Enhancements to adaptive query processing, including the ability to adaptively create and update statistics for better query performance.

  • Support for graph database features, including the ability to create graph indexes for querying graph data.

SQL Server 2019:

  • Introduces support for accelerated database recovery, which reduces the time required to recover a database after a crash or restart.

  • Enhancements to intelligent query processing, including batch mode on rowstore and approximate query processing for improved query performance.

  • Continues support for all previous types of indexes with further enhancements and optimizations.

What Are Indexes In SQL Server

In SQL Server, indexes are database objects designed to enhance the performance of data retrieval operations by facilitating faster access to rows within a table. They serve as structured data structures storing sorted copies of selected columns from a table, along with pointers to corresponding rows in the table.

Indexes function akin to the index found in a book, enabling SQL Server to swiftly locate specific rows without scanning the entire table. Upon executing a query against a table with an index, SQL Server can utilize the index to promptly find relevant rows based on the query's search criteria.

SQL Server supports various types of indexes, each tailored to specific query types and data access patterns:

  • Clustered Index: Determines the physical order of rows in the table, with each table hosting only one clustered index as the physical order can be arranged in just one way. When creating a clustered index, data in the table is reorganized to match the order of the clustered index key.

  • Non-Clustered Index: Operates as a separate structure from the table, housing a sorted copy of chosen columns alongside pointers to corresponding rows. Unlike clustered indexes, non-clustered ones don't influence the physical row order, permitting multiple non-clustered indexes on a single table, each optimized for distinct query patterns.

  • Unique Index: Ensures uniqueness of values across indexed columns within the table. Similar to non-clustered indexes, unique indexes don't affect the physical row order.

  • Filtered Index: A non-clustered index containing only a subset of table rows based on a filter condition. These indexes improve query performance for specific data subsets within the table.

Indexes are instrumental in optimizing query performance by reducing the data scanned and retrieved from disk. Nonetheless, their creation and maintenance entail overhead in terms of storage and operations, necessitating careful consideration of the indexing strategy tailored to the database's workload and query patterns.


Clustered Index: Benefits:

  • Efficient for range queries and sorting operations since data is physically stored in sorted order.

  • Avoids the need for a separate lookup when accessing rows based on the clustered index key.

  • Typically used on columns with unique or semi-unique values, such as primary keys or columns frequently used in range queries.

Clustered Index Issues:

  • Inserts can be slower compared to non-clustered indexes because SQL Server needs to rearrange data to maintain the sort order.

  • Updates to the clustered index key can cause page splits and fragmentation, leading to decreased performance.

  • Only one clustered index can be created per table, limiting the options for indexing strategies.

Non-Clustered Index: Benefits:

  • Can be created on any column or combination of columns, providing flexibility in indexing strategies.

  • Does not affect the physical order of the data, allowing for faster insert and update operations compared to clustered indexes.

  • Supports multiple non-clustered indexes per table, enabling indexing on different query patterns.

Non-Clustered Index:

  • Requires an additional lookup to retrieve row data not included in the index, which can impact performance for queries that access many columns or perform range scans.

  • Requires additional storage space for the index structure.

  • Updates to indexed columns can lead to fragmentation and decreased performance over time.

Unique Index: Benefits:

  • Enforces uniqueness on one or more columns, preventing duplicate values in the indexed columns.

  • Can be used to optimize query performance for unique or semi-unique columns.

  • Supports both clustered and non-clustered index types.

Unique Index

  • Requires additional processing overhead for enforcing uniqueness constraints during inserts and updates.

  • May lead to contention and blocking in multi-user environments when multiple transactions attempt to insert or update rows with conflicting values.

Filtered Index: Benefits:

  • Reduces index size and maintenance overhead by including only a subset of rows in the index.

  • Improves query performance for specific subsets of data by optimizing index usage.

  • Allows for more targeted indexing strategies to address specific query patterns.

Issues:

  • Requires careful selection of filter conditions to ensure that the index is selective and useful for the intended queries.

  • May become less effective if the data distribution changes over time, requiring periodic review and adjustment of filter conditions.

  • Introduces additional complexity to index maintenance and query optimization.


How To Can I See Indexes In SQL Server Management Studio


In SQL Server Management Studio (SSMS), you can easily view the indexes associated with a table using the Object Explorer.


Here's how you can do it:

  • Open SQL Server Management Studio.

  • Connect to your SQL Server instance.

  • In the Object Explorer pane on the left-hand side, navigate to the database that contains the table for which you want to see the indexes.

  • Expand the database node to reveal its contents, including tables, views, and other objects.

  • Expand the "Tables" node to see the list of tables in the database.

  • Find the table for which you want to view the indexes, then expand its node.

  • Expand the "Indexes" node underneath the table.

You should now see a list of indexes associated with the selected table. This list will include both clustered and non-clustered indexes, if any, along with their names, types, and key columns.

Additionally, you can view index properties by right-clicking on an index and selecting "Properties". This will provide more detailed information about the index, including its definition, included columns, and storage properties.

Using SSMS, you can easily explore and manage indexes as part of your database administration tasks.


Identifying Indexing Needs With A Report


Once you've accessed the Index Usage Statistics report, you'll see a table with the following columns:

  • Table Name: The name of the table associated with the index.

  • Index Name: The name of the index being analyzed.

  • Index Type: Specifies whether the index is clustered or non-clustered.

  • User Seeks: The number of seeks (index seeks) performed on the index by user queries.

  • User Scans: The number of scans performed on the index by user queries.

  • User Lookups: The number of lookups performed on the index by user queries.

  • User Updates: The number of updates (inserts, updates, deletes) made to the index by user queries.

Interpreting the results:

  • User Seeks: A high number of seeks indicates that the index is being utilized efficiently for selective queries.

  • User Scans: Scans may indicate that the index is being used for range queries or that it's being scanned entirely due to lack of suitable indexes.

  • User Lookups: Lookups occur when data not included in the index is required, leading to additional reads. Minimizing lookups can improve query performance.

  • User Updates: High numbers of updates on an index may indicate heavy write activity, which could impact its performance.

Based on the information provided in the report, you can make informed decisions about index maintenance, optimization, or removal. For example, indexes with high usage statistics may be critical for performance and should be retained, while indexes with low usage statistics may be candidates for review to determine if they're necessary.


Identifying Indexing Needs With T-SQL

Viewing index usage statistics in SQL Server is crucial for understanding how indexes are being utilized within your database. By examining index usage patterns, you can identify frequently accessed tables and columns, as well as unused indexes that may be candidates for removal to improve performance. Here's how you can accomplish this using T-SQL examples:

A. Querying dynamic management views (DMVs) such as sys.dm_db_index_usage_stats:

-- Query sys.dm_db_index_usage_stats to view index usage statistics
SELECT 
    OBJECT_NAME(s.object_id) AS 'TableName',
    i.name AS 'IndexName',
    i.type_desc AS 'IndexType',
    us.user_seeks AS 'Seeks',
    us.user_scans AS 'Scans',
    us.user_lookups AS 'Lookups',
    us.user_updates AS 'Updates',
    us.last_user_seek AS 'LastSeek',
    us.last_user_scan AS 'LastScan',
    us.last_user_lookup AS 'LastLookup',
    us.last_user_update AS 'LastUpdate'
FROM 
    sys.dm_db_index_usage_stats us
JOIN 
    sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
JOIN 
    sys.objects s ON s.object_id = us.object_id
ORDER BY 
    us.user_seeks + us.user_scans + us.user_lookups DESC;

B. Examining index usage patterns to identify frequently accessed tables and columns:

-- Identify frequently accessed tables and columns based on index usage statistics
SELECT 
    OBJECT_NAME(s.object_id) AS 'TableName',
    c.name AS 'ColumnName',
    i.name AS 'IndexName',
    us.user_seeks + us.user_scans + us.user_lookups AS 'TotalAccesses'
FROM 
    sys.dm_db_index_usage_stats us
JOIN 
    sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
JOIN 
    sys.objects s ON s.object_id = us.object_id
JOIN 
    sys.index_columns ic ON ic.object_id = us.object_id AND ic.index_id = us.index_id
JOIN 
    sys.columns c ON c.object_id = us.object_id AND c.column_id = ic.column_id
WHERE 
    c.name IS NOT NULL
ORDER BY 
    TotalAccesses DESC;

C. Identifying unused indexes for potential removal to improve performance:

-- Identify unused indexes based on index usage statistics
SELECT 
    OBJECT_NAME(object_id) AS 'TableName',
    index_id AS 'IndexID',
    name AS 'IndexName',
    user_seeks,
    user_scans,
    user_lookups,
    user_updates
FROM 
    sys.dm_db_index_usage_stats
WHERE 
    user_seeks = 0 
    AND user_scans = 0 
    AND user_lookups = 0 
    AND user_updates > 0;

By querying dynamic management views such as sys.dm_db_index_usage_stats, you can gain valuable insights into how indexes are being used within your SQL Server database. Use this information to optimize index usage, identify frequently accessed tables and columns, and remove unused indexes to improve overall database performance.

Write about how to view Index Usage Statistics, please give t-SQL examples and cover the topics below. Please make sure to explaign what each t-SQL query does how to interperate the results. A. Querying dynamic management views (DMVs) such as sys.dm_db_index_usage_stats B. Examining index usage patterns to identify frequently accessed tables and columns C. Identifying unused indexes for potential removal to improve performance

Querying dynamic management views (DMVs) such as sys.dm_db_index_usage_stats:

The sys.dm_db_index_usage_stats DMV provides valuable information about index usage within a database. It tracks usage statistics for indexes, such as the number of seeks, scans, lookups, and updates performed since the last SQL Server service restart or since the index was created.


Here's how you can query this DMV:

SELECT 
    OBJECT_NAME(s.object_id) AS TableName,
    i.name AS IndexName,
    i.type_desc AS IndexType,
    us.user_seeks AS Seeks,
    us.user_scans AS Scans,
    us.user_lookups AS Lookups,
    us.user_updates AS Updates,
    us.last_user_seek AS LastSeek,
    us.last_user_scan AS LastScan,
    us.last_user_lookup AS LastLookup,
    us.last_user_update AS LastUpdate
FROM 
    sys.dm_db_index_usage_stats us
JOIN 
    sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
JOIN 
    sys.objects s ON s.object_id = us.object_id
ORDER BY 
    us.user_seeks + us.user_scans + us.user_lookups DESC;

Interpreting the results:

  • TableName: The name of the table containing the index.

  • IndexName: The name of the index.

  • IndexType: The type of index (e.g., clustered, nonclustered).

  • Seeks: The number of seeks performed on the index.

  • Scans: The number of scans performed on the index.

  • Lookups: The number of lookups performed on the index.

  • Updates: The number of updates performed on the index.

  • LastSeek, LastScan, LastLookup, LastUpdate: The last time a seek, scan, lookup, or update operation was performed on the index.

B. Examining index usage patterns to identify frequently accessed tables and columns:

To identify frequently accessed tables and columns based on index usage statistics, you can join sys.dm_db_index_usage_stats with other system tables to retrieve information about tables and columns associated with the indexes.


Here's an example query:

SELECT 
    OBJECT_NAME(s.object_id) AS TableName,
    c.name AS ColumnName,
    i.name AS IndexName,
    us.user_seeks + us.user_scans + us.user_lookups AS TotalAccesses
FROM 
    sys.dm_db_index_usage_stats us
JOIN 
    sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
JOIN 
    sys.objects s ON s.object_id = us.object_id
JOIN 
    sys.index_columns ic ON ic.object_id = us.object_id AND ic.index_id = us.index_id
JOIN 
    sys.columns c ON c.object_id = us.object_id AND c.column_id = ic.column_id
WHERE 
    c.name IS NOT NULL
ORDER BY 
    TotalAccesses DESC;

Interpreting the results:

  • TableName: The name of the table containing the index.

  • ColumnName: The name of the column associated with the index.

  • IndexName: The name of the index.

  • TotalAccesses: The total number of seeks, scans, and lookups performed on the index.

C. Identifying unused indexes for potential removal to improve performance:

Unused indexes can impact performance and consume storage space without providing any benefit. To identify unused indexes, you can query sys.dm_db_index_usage_stats to find indexes with zero seeks, scans, and lookups, but with non-zero updates.


Here's how you can do it:

SELECT 
    OBJECT_NAME(object_id) AS TableName,
    index_id AS IndexID,
    name AS IndexName,
    user_seeks,
    user_scans,
    user_lookups,
    user_updates
FROM 
    sys.dm_db_index_usage_stats
WHERE 
    user_seeks = 0 
    AND user_scans = 0 
    AND user_lookups = 0 
    AND user_updates > 0;

Interpreting the results:

  • TableName: The name of the table containing the index.

  • IndexID: The ID of the index.

  • IndexName: The name of the index.

  • user_seeks, user_scans, user_lookups: The number of seeks, scans, and lookups performed on the index (should be zero).

  • user_updates: The number of updates performed on the index (non-zero indicates the index has been modified).

By analyzing index usage statistics, you can gain insights into how indexes are being utilized in your database and make informed decisions about index maintenance and optimization.

Conclusion

Indexing is an ever-evolving field that demands a combination of theoretical understanding and hands-on experience. As we conclude, a reiteration of the key takeaways will serve as a compass to guide your future indexing endeavors. A final word on the holistic impact of indexing on your database will underscore the significance of this often underestimated aspect of SQL Server management.


Additional Information




Recent Posts

See All

Get in Touch

Thanks for submitting!

bottom of page