I was working with a 1.3 trillion row table in the Microsoft lab when I learned more about the ins and outs of this behavior. This issue is alluded to in SQL Server Books Online but allow me to expand on the behavior a bit more. (http://msdn.microsoft.com/en-us/library/ms190787.aspx)
The lab machine is a 128GB, 64 CPU system running enterprise editions of Windows and SQL Server.
- When I built an index on a 25 million row table, non-partitioned the MAX DOP selected for the index build was 64.
- When I built an index on the 1.3 trillion row table, partitioned (27 total partitions) the MAX DOP selected for the index build was 27.
I spent some time looking at and tuning the maximum query grant and sp_configure index memory settings without seeing any change in MAX DOP = 27 behavior.
After reading over SQL Server Books Online and stepping through the SQL Server (CalculateDOP) logic the answer was clear.
There are certain operations against a partitioned table (create and alter index are a few of these) that leverage the partitioning when performing range operations. The partition ranges are then used to drive the maximum possible, runtime DOP level.
First, SQL Server limits the maximum possible DOP = MIN(64, CPUs). If you only have 32 CPUs the MAX DOP possible will be 32. If you have 160 CPUs the MAX DOP possible will be 64.
Then for some operations, such as create index, the partitions are considered. When performing a create/alter index with range partitioning: MIN(Partitions, MIN(64, CPUS)).
Note: The formulas presented here assume sp_configure max degree of parallelism=0 and no other resource governor or query option was established. You may use the MAXDOP query or resource governor options to alter the runtime DOP selections.
In my test case the I had 64 CPUs so the MIN becomes the partitions = 27. This is a very practical choice in many situations as the partitions usually line up with hardware and running DOP = partitions in this way is very efficient and inline with the DBAs database design decisions.
The specific index build I was doing was very CPU intensive (Spatial) activities and from testing I knew if I achieved additional runtime DOP I could build the index faster (knowing I consume more resources at the possible expense of other activity!)
Evenly splitting the partitioned table into at least as many partitions as I have MIN(64, CPUS) CPU resources allowed me to apply more CPU resources to the create index operation.
In my specific scenario the 1.3 trillion row, spatial index builds in ~4.5 hours @ 27 CPUs and ~2.3 hours @ 64 CPUs.
WARNING: Increasing the runtime DOP does not always provide improved performance. The additional overhead may put pressure on memory, I/O and impact performance of other queries as the additional resources are consumed. You should test carefully but consider your partitioned layout in order to optimize your DOP capabilities.
Specific Partition Index Builds
You should also be aware that the partition scheme and index may limit the MAXDOP when rebuilding a specific index on a specific partition. For some indexes you are allowed to rebuild a partitioned index for a specific partition. This may use the partition’s range and limit the index rebuild to MAXDOP=1 where a similar index build on a non-partitioned table may use an increased DOP level.
Bob Dorr - Principal SQL Server Escalation Engineer