To improve customer workload performance and reduce unnecessary resource utilization, the default MAXDOP setting for new databases in Azure SQL Database is changing from the previous default of 0 (unlimited) to 8.
Why MAXDOP matters
The “max degree of parallelism” (a.k.a. MAXDOP) SQL Server configuration option controls the ability of the database engine to use parallel threads during query processing. When MAXDOP is other than 1, the database engine may execute queries using multiple concurrent threads. This often results in shorter query duration due to additional CPU resources used for query processing. The number of concurrently executing threads, and the resulting CPU utilization, depends on the MAXDOP value. Higher values generally result in more threads and higher resource utilization.
If a query is using parallelism, it often gets faster as MAXDOP is increased, though after some point additional threads may just use extra CPU cycles without reducing query duration. To learn more about query parallelism, see the Degree of Parallelism section in the Query Processing Architecture Guide.
Azure SQL uses the SQL Server database engine, thus MAXDOP considerations and recommendations for SQL Server are also applicable to Azure SQL. This includes single databases, databases in elastic pools, and managed instances. For all of these deployment options, customers can control MAXDOP at the database level using the MAXDOP database-scoped configuration. For managed instances, customers can also set the server ‘max degree of parallelism’ configuration option, and can control MAXDOP at the Resource Governor workload group level. For all Azure SQL deployment options, MAXDOP can additionally be controlled at the individual query level by using the OPTION (MAXDOP) query hint, which overrides MAXDOP configurations set in the database or instance scope (though without exceeding the Resource Governor workload group cap, if any).
Changing MAXDOP can have major impact on query performance and resource utilization, both positive and negative. However, there is not a single MAXDOP value that is optimal for all workloads. The recommendations for setting MAXDOP are nuanced, and depend on many factors. Customers wishing to achieve optimal performance for their workloads may need to fine-tune MAXDOP, using published recommendations as the starting point.
Importantly, while increasing MAXDOP often reduces duration for long-running queries, excessive parallelism can cause unnecessary CPU and worker utilization, and make the overall workload performance worse by starving other queries of these resources. In extreme cases, excessive parallelism can consume all database or elastic pool resources, causing query timeouts, errors, and application outages.
Historically, the default MAXDOP value in SQL Server has always been set to 0. This means that query parallelism is limited only by the hardware bounds of the machine running the SQL Server instance (up to the maximum MAXDOP of 64). For backward compatibility reasons, this remains the default value in SQL Server, though starting with SQL Server 2019, it is possible to change the instance level MAXDOP during initial instance setup.
In Azure SQL Database, the default MAXDOP value has also been set to 0 (unlimited) for every new database, for similar reasons. However, over time, and especially as databases and elastic pools with many cores became widely used, performance problems due to excessive parallelism caused by MAXDOP set to 0 became more frequent. This particularly impacts customers who are not familiar with the MAXDOP option, and leave it at the default of 0.
To address these performance problems, we are making the following change:
For every new single database and elastic pool database, the MAXDOP database-scoped configuration will be set to 8 by default.
Frequently Asked Questions
Why are you changing default MAXDOP for new Azure SQL databases?
This change is to reduce the frequency and severity of incidents caused by excessive query parallelism, and to improve customer workload performance by reducing unnecessary resource utilization. We expect that this change will benefit the overwhelming majority of customers using Azure SQL Database.
When will this change happen?
We expect this change to roll out worldwide in August of 2020.
Will this change impact my existing Azure SQL databases?
No. Existing databases will not be modified. This change applies only to new databases created after this change is rolled out.
Does this change apply to Azure SQL Managed Instance?
No, at this time this change only applies to single databases and databases in elastic pools in Azure SQL Database.
I know that MAXDOP setting different from 8 is optimal for my workload. What should I do?
Customers who have determined that a specific MAXDOP setting is optimal for their workloads, or customers who prefer to keep MAXDOP 0 used previously by default, can add a step to their database deployment processes to change MAXDOP after database creation.
Should I change MAXDOP on my existing Azure SQL databases?
Customers with existing databases that use the default MAXDOP 0 should consider changing MAXDOP according to standing recommendations. This may improve performance, reduce the risk of performance and availability incidents, and in some cases reduce costs by being able to avoid unnecessary resource utilization, and thus scale down to a lower service objective.
We recommend that customers avoid MAXDOP 0 even if it does not appear to cause problems currently. This will reduce the risk of potential future problems due to excessive parallelism if a database is scaled up to use more cores, or if future hardware generations in Azure SQL provide more cores for the same database service objective.
As with most configuration changes, thorough testing is recommended before making changes in critical environments.
How can I change MAXDOP for an existing database?
MAXDOP can be changed using the ALTER DATABASE SCOPED CONFIGURATION statement in the scope of a database.
To execute the necessary T-SQL statement, customers can use any client tool or programming language that can connect to the database and execute T-SQL commands. The following client tools are commonly used:
For example, to change MAXDOP to 4, use the following T-SQL command when connected to the target database:
How do I know if a change to MAXDOP made a difference for my workload?
Customers can see the impact of a change in MAXDOP by making sure that Query Store is enabled for a representative period of time before and after the change is made, to capture resource utilization and performance statistics for each query. For more details, see A/B testing.
What are the symptoms of excessive query parallelism in Azure SQL Database?
In Azure SQL Database, one common symptom of excessive parallelism is exceeding the resource governance limits on the number of worker threads. When this happens, error 10928, “Resource ID : 1. The request limit for the database is N and has been reached” is raised, where N stands for the worker thread limit for the database or elastic pool (note, however, that there are other possible causes for this error).
CXPACKET waits may be another symptom of excessive parallelism. Some amount of CXPACKET waits is normal whenever query parallelism is used; however, if CXPACKET waits dominate other waits types while CPU utilization is greater than 80-90%, it likely also indicates excessive parallelism.
Why did you choose 8 as the new default MAXDOP?
Our telemetry data and our experience running the Azure SQL Database service show that MAXDOP 8 is the optimal value for the widest variety of customer workloads. It is a safe option that reduces the likelihood of performance problems due to excessive parallelism, while still allowing queries to execute faster by using more threads.
At the same time, workloads where a different MAXDOP value is optimal do exist. Customers can experiment with different MAXDOP settings to determine what works best for them.
Shouldn’t the database engine automatically choose the optimal degree of parallelism for every query it executes?
Improvements in Azure SQL and the SQL Server database engine are made continuously. Automatic Tuning, and the Intelligent Query Processing family of features are two examples of improvements in query processing and query performance made in recent years. Today, the database engine already reduces query parallelism at query startup time in response to a shortage of available worker threads. Query processing improvements in future releases of the database engine may adjust parallelism dynamically in a broader set of scenarios.
Why are you changing the default MAXDOP regardless of the database service objective? Shouldn’t this only apply to databases with more than 8 cores?
Limiting MAXDOP to 8 is safe for databases with 8 or less cores (or scheduler threads). In this case, parallelism will be limited by the smaller number of available cores, rather than by the MAXDOP setting. Limiting MAXDOP to 8 protects smaller databases from being exposed to excessive parallelism if scaled up to use more than 8 cores, or if future hardware generations in Azure SQL Database provide more cores for the same database service objective.
What is the impact of this change on index rebuild?
By default, indexes are rebuilt with parallelism, using the database-scoped MAXDOP setting. On databases with more than 8 cores, this change may cause index rebuilds to take longer due to lower degree of parallelism used. If this happens, you can increase parallelism for each index rebuild operation by using the MAXDOP option in the ALTER INDEX … REBUILD statement.
How can I ask questions or provide feedback on this change?
Customers can ask questions or provide feedback via comments to this blog post, or via email to IntelligentQP [at] microsoft.com.