04/07/2024

Execution Plan Changes in SQL Server: Reasons and Solutions

Executions plan—complex maps charted by the SQL Server optimizer, dictate the most efficient route for data retrieval. However, the plans are not static. They morph and adapt, influenced by a host of factors ranging from data volume changes to system upgrades. Each of the execution plan changes in SQL Server has the potential to sway performance dramatically.

Understanding the reasons behind these shifts, and more importantly, how to effectively manage them translates to maintaining optimal performance in SQL Server environments. 

Data Changes

One of the most common triggers for execution plan changes in SQL Server is a great alteration in data volume within the database tables. Why? SQL Server employs a mechanism; it maintains statistics about the data stored in the database. These statistics are then used by the Query Optimizer to determine the most efficient way to execute a query. When data changes—through large-scale insertions, deletions, or updates—these statistics diverge from the current state of the data.

SQL Server sets thresholds for how much data in a table must change before it automatically updates the table’s statistics. Typically, this threshold is around 20% of the rows in the table. Once this threshold is crossed, SQL Server marks the statistics as outdated. At the next query execution that would use these statistics, the Query Optimizer may choose to update the statistics first. Then, based on this fresh data, it can generate a new execution plan.

This behavior is fundamentally designed to keep the execution plans as efficient as possible. However, if the data change is abrupt or continuous, it might lead to frequent (and annoying) shifts in the execution plans. 

Statistics Getting Out of Date Leading to Execution Plan Changes in SQL Server

Statistics in SQL Server provide a summary of the data distribution in the tables. This includes information such as the average value, minimum and maximum values, and the distribution of values within each column. These summaries help the optimizer predict how many rows will be affected by a query. This, in turn, influences the chosen execution strategy.

As execution plan changes in SQL Server accumulate in the database, the accuracy of these statistics fades. This decay in relevance can mislead the optimizer. In certain cases, the optimizer may choose an index scan when an index seek would be more appropriate, or it might misjudge the number of rows returned by a filter, leading to suboptimal join methods or improper memory grants.

The implications of this misinformation are painful:

  • Inefficient Query Performance: The optimizer might choose a plan that performs poorly because it’s based on stale statistics. This can cause queries that once executed quickly to run slower, consuming more resources such as CPU and I/O, leading to broader system performance issues.
  • Resource Misallocation: Incorrect estimates can lead to either over or under-utilization of SQL Server resources. Overestimations can cause SQL Server to reserve more memory than necessary, leaving less available for other processes. Underestimations might lead to insufficient memory allocation, causing frequent disk I/O that could have been avoided.

Reducing the Follout of Statistics Getting Out of Date

  • Manual Update of Statistics: Use UPDATE STATISTICS after significant data changes to ensure statistics accurately reflect the current state of data, helping maintain optimal query performance.
  • Adjusting the Statistics Update Threshold: Modify the default settings in SQL Server to lower the automatic statistics update threshold. This should result in more frequent updates without manual intervention.
  • Implementing Asynchronous Statistics Updates: Enable AUTO_UPDATE_STATISTICS_ASYNC to allow updates to occur in the background, preventing query delays and ensuring that execution plans are based on the latest data.

Index Health

Index health is one of the most weighty factors in SQL Server’s ability to choose the most efficient execution plan for a query. When indexes are well-maintained, they provide fast pathways to the data, which the optimizer uses to construct high-performance plans. However, issues such as index fragmentation have the potential to severely impact these decisions, leading to less optimal query performance.

Fragmentation: Over time, as data is modified in the database—insertions, updates, deletions—indexes can become fragmented. This fragmentation implies that the logical order of the index data becomes scattered, not aligning with the physical order on the disk. The consequences are:

  • Increased I/O Operations: Fragmented indexes cause the good old SQL Server to perform more I/O operations, as the data pages are not contiguous. This, in turn, makes the engine read multiple pages from different locations on the disk.
  • Inefficient Execution Plans: The optimizer, bases its decisions on the physical layout and statistics of the indexes. If the index’s fragmentation leads to a misestimation of the cost associated with using the index, the optimized is more likely to opt for a table scan instead of using a fragmented index.

Solutions:

  • Index Maintenance: Regular maintenance tasks such as rebuilding or reorganizing indexes can mitigate fragmentation. The choice between rebuilding and reorganizing depends on the degree of fragmentation:
    • Rebuilding Indexes: This process creates a new version of the index, eliminating fragmentation, reclaiming disk space, and reordering the index rows according to their logical order. A rebuild is generally more resource-intensive and is advisable when fragmentation is severe.
    • Reorganizing Indexes: Less intensive than a rebuild, reorganization physically reorders the leaf-level pages to match the logical order. It’s a lighter operation and can be performed more frequently as a preventive measure against fragmentation.
  • Regular Monitoring
  • Tools and Features: take advantage of features such as the SQL Server Agent to automate the index maintenance process. Tools like SQL Server Management Studio (SSMS) provide built-in reports and dashboards to monitor index health and performance.

Query and Schema Modifications

When you play with the structure of a query or adjust the database schema, the ripples, just like a small pebble thrown into a large pond, affect the entire surface. Even small alterations can compel SQL Server to generate new execution plans.

  • Changing Joins: Altering how tables relate can shift the data retrieval path more dramatically than rerouting a major highway.
  • Adjusting Filters: Modifying WHERE clauses does more than filter data differently—it can change the data retrieval environment entirely.
  • Introducing New Operations: Adding elements like GROUP BY or ORDER BY transforms the query’s demands, asking for data in new ways that can strain the system in different manners.

Schema Modifications: Changing the database schema can also have far-reaching implications:

  • Index Adjustments: Adding or removing indexes can make navigation easier or add to confusion, affecting the speed and efficiency of data retrieval.
  • Modifying columns: Changing data types, adding NULL constraints, or altering column sizes can affect how data is stored and accessed, requiring new execution plans to handle these changes effectively.
  • Adjusting constraints and relationships: Changes to primary keys, foreign keys, or check constraints might alter the data integrity rules and relationships between tables, impacting join behaviors and the validity of existing execution plans.

Solutions:

  • Testing: Implementing changes in a controlled environment allows for the assessment of impact on performance, providing a glimpse into potential real-world issues.
  • Refresh Statistics: Updating statistics after making modifications guarantees that the optimizer has the most current data.
  • Ongoing Monitoring: Continuous monitoring of query performance and execution plans after changes helps in quickly identifying and rectifying inefficient executions.

SQL Server Upgrades

Updates of SQL Server are usually followed by modifications to the query optimizer, which is responsible for deciding the most efficient way to execute queries. The evolution of the optimizer can lead to differences in how execution plans are determined.

One of the most significant changes that can occur with an upgrade is the modification of the cardinality estimator. It´s duty is to predict the number of rows processed by various query operations, which heavily influences the choice of execution plan. Upgrades can refine these predictions, meaningÑ different plan choices that might not align with previous optimizations.

Solutions:

  • Thorough Testing: This testing should include performance benchmarks to identify any potential regressions.
  • Plan Management: SQL Server provides tools such as Query Store to capture and preserve good execution plans. This can be used to force the use of these plans even after an upgrade until a more permanent solution is viable.
  • Gradual Rollouts: Applying upgrades gradually across environments allows teams to monitor the impact and adjust strategies as needed.

Server Configuration Changes

Obviously enough, the way execution plans are formed and executed is not indifferent to server configuration settings.

One key setting that often affects execution plan choices is the Maximum Degree of Parallelism (MAXDOP). It determines the number of processors that SQL Server can use for the parallel execution of queries. When you modify MAXDOP, you are essentially dictating how many CPU cores SQL Server can use for processing queries in parallel. A lower MAXDOP restricts the server to fewer cores, pushing it towards more sequential query processing. Setting a higher MAXDOP encourages the server to leverage more cores for executing complex queries faster, though this can lead to increased contention among processes if not managed carefully.

These changes, however, do not occur in a vacuum. They recalibrate the fundamental behavior of SQL Server’s query optimizer. This recalibration can sometimes lead to a scenario where previously cached plans become suboptimal under new settings, prompting SQL Server to recompile queries under the new system configuration. This recompilation, while necessary, can lead to transient performance dips as the server adjusts to the new settings.

Handling the Execution Plan Changes in SQL Server

  • Gradual Adjustments: Make incremental changes to settings like MAXDOP rather than large adjustments, to better gauge their impact.
  • Use Baselines: Performance baselines set up before making changes can be instrumental in measuring the effectiveness of a configuration change.
  • Consult Best Practices: Adhere to Microsoft’s best practices for configuration settings. SQL Server documentation and community recommendations can provide guidance in this matter.

Parameter Sniffing

Parameter sniffing refers to SQL Server’s optimization behavior, where the query optimizer examines the parameter values passed during the first execution of a stored procedure and creates a plan based on those values. This process is generally a positive thing—it tailors the execution plan to match the specific query workload. But there are moments and situations when parameter sniffing can lead to performance issues when the same execution plan is reused for significantly different parameter values.

When the initial parameter values are not representative of typical usage, the optimized plan might not be ideal for subsequent executions with different parameters. This can lead to inefficient query performance, longer execution times, and increased resource utilization.

Let’s take an example. If a stored procedure is first executed with a parameter that retrieves a small subset of rows, the query optimizer might choose a plan that uses an index seek—highly efficient for small data sets. If the same plan is used for a parameter that needs to retrieve a larger set of rows, the plan might not scale well, leading to slower performance and higher resource demands.

Dealing with Parameter Sniffing Issues

  • Query Store and Plan Forcing: SQL Server’s Query Store feature allows capturing and storing detailed performance data for queries along with their plans. Administrators can manually force the use of specific plans that are known to perform well for certain queries, thereby sidestepping the detrimental effects of parameter sniffing.
  • Plan Guides: Plan guides allow SQL Server people to attach query hints or fixed plans to specific queries, helping to control the execution plan choice— no direct modifying the application code required.