SQL Server – Why OPTION (MAXDOP 1) Appears in Actual Query Plan

performanceperformance-testingperformance-tuningsql serversql-server-2012

SQL Server is set with MAXDOP 0 by default. In the stored procedure I'm testing I keep seeing WITH (MAXDOP 1) in the Actual Execution Plans even though I've not specified any hints other than SORT_IN_TEMPDB = 1. The main Stored Procedure calls another procedure which grabs the table, generates scripts on each disabled index, then executes that series of scripts (with the afformentioned query hint). The funny thing is I'm seeing a high CPU cost for the operation so I imagine there's benefits to parallelism.

The table has a few million rows and is very wide.

Unfortunately, the database is file and TempDB file are on the same datastore and the TempDB is just 1 file as opposed to several. This configuration is out of my control but perhaps it's related to the reason for no parallelism.

The server is on a VM with 4 cores and 64 GB RAM.

Any thoughts on why SQL Server insists on dropping parallelism on such a large operation on a large table?

EDIT: Added script for the Inner stored procedure that gets called during Upserts:

CREATE PROCEDURE etl_Index_EnableDisable
@DatabaseName NVARCHAR(50)
,@TableName NVARCHAR(50)
,@EnableDisable NVARCHAR(50)

AS
BEGIN

 IF @DatabaseName IS NULL
   RAISERROR('Null values not allowed for @DatabaseName', 16, 1)
 IF @TableName IS NULL
   RAISERROR('Null values not allowed for @TableName', 16, 1)
 IF @EnableDisable IS NULL
   RAISERROR('Null values not allowed for @EnableDisable', 16, 1)

 DECLARE @SQL NVARCHAR(4000)

 -- Interpret 1 as enable and 0 as disable. Also set to Upper case
 SET @EnableDisable = CASE UPPER(@EnableDisable) WHEN '1' THEN 'ENABLE' 
                                                 WHEN 'REBUILD' THEN 'ENABLE' 
                                                 WHEN '0' THEN 'DISABLE' 
                                                 ELSE UPPER(@EnableDisable) 
                      END


 SET @SQL = ' DECLARE @SQLIn NVARCHAR(4000)  
              SELECT @SQLIn = COALESCE(@SQLIn,'' '') 
              +  SQL1 FROM ( (SELECT '' ALTER INDEX '' + si.name + '' ON ' + @DatabaseName + ' .dbo.'' + st.name + ' + CASE @EnableDisable WHEN 'DISABLE' THEN ''' DISABLE ''' 
                                                                                                                     WHEN 'ENABLE' THEN ''' REBUILD WITH (SORT_IN_TEMPDB = ON) ''' END + '
                 AS SQL1
                  FROM ' + @DatabaseName + '.Sys.indexes si
                       JOIN  ' + @DatabaseName + '.Sys.tables st ON si.object_id = st.object_id
                  WHERE st.name = ''' + @TableName + '''
                        AND (si.is_unique = 0
                             AND si.is_unique = 0
                             AND si.is_primary_key = 0
                            AND si.[type] = 2
                            )
                       AND si.is_disabled = ' + CASE @EnableDisable WHEN 'DISABLE' THEN '0'
                                                                    WHEN 'ENABLE' THEN '1' 
                                                END + '
                       AND si.Name IS NOT NULL
               ) ) tb

             EXEC sp_sqlexec @SQLIn '

 EXEC sp_sqlexec @SQL

END`

Best Answer

You are performing an index rebuild on Standard edition.

As documented here you would need Enterprise or Developer edition to see parallelism for this.