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.