By David Erickson, RedPrairie
Most of you know that computer CPUs are not getting faster anymore, instead they are getting more cores. Microsoft SQL Server has two parameters that control whether work goes to one core or to many cores. I'd like to give a simple explanation of these two factors and share my experience tuning them in our labs. You may discover a significant performance improvement from your RedPrairie database.
Note: Often a core is referred to as a logical processor in Microsoft documentation.
Where are the Parallelism Parameters?
In SQL Server Management Studio (SSMS):
The default value for MAXDOP is 0 and means that SQL Server may use up to the max CPUs available in any parallel plan. If MAXDOP is set to 1 SQL Server will use exactly 1 CPU, i.e. parallel plan execution is disabled. Any other value will cause SQL Server to use up to the specified number of CPUs in the parallel plan.
If you search the web, you will find a lot of speculation on what is the best value. My personal stance is as follows.
There is a need for balance - the parallel plan will consume more resources, but theoretically free those resources (and any locks) in a shorter period of time. A system with shorter locks is truly better for contention and reduces the duration of blockages.
I’ve heard several Microsoft experts say that this feature is more intended for BI or OLAP type systems, with fewer concurrent users, rather than OLTP systems with higher concurrency requirements. Very recently, I had the chance to revisit this topic again with a Microsoft SQL Server performance expert. We came up with an approach that I think is pretty reasonable for many customers.
The Script
To make your life simpler, I've included a script below that will create two SQL Server Agent Jobs. The first one sets 'max degree of parallelism' to 1 at 6AM. The second job sets 'max degree of parallelism' to 1/2 of the number of cores at 1 AM. Adjust the hours to your own environment if needed.
Script for regular production
USE [msdb]GOBEGIN TRANSACTIONDECLARE @ReturnCode INTSELECT @ReturnCode = 0IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Parallelism]' AND category_class=1)BEGINEXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Parallelism]'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'Change Maximum Degree of Parallelism to 1', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'No description available.', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'SERVER2008X64\Administrator', @job_id = @jobId OUTPUTIF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'SetParallelToOne', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'sp_configure ''show advanced options'', 1;GORECONFIGURE WITH OVERRIDE;GOsp_configure ''max degree of parallelism'', 1;GORECONFIGURE WITH OVERRIDE;GO', @database_name=N'master', @flags=0IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'At 6AM', @enabled=1, @freq_type=4, @freq_interval=1, @freq_subday_type=1, @freq_subday_interval=0, @freq_relative_interval=0, @freq_recurrence_factor=0, @active_start_date=20110627, @active_end_date=99991231, @active_start_time=60000, @active_end_time=235959, @schedule_uid=N'40a4c2b4-56fa-4a0b-a22a-f0bb15788539'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackCOMMIT TRANSACTIONGOTO EndSaveQuitWithRollback: IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTIONEndSave:GO
Script for Batch Processing
USE [msdb]GOBEGIN TRANSACTIONDECLARE @ReturnCode INTSELECT @ReturnCode = 0IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Parallelism]' AND category_class=1)BEGINEXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Parallelism]'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'Change Maximum Degree of Parallelism to Half CPUS', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'No description available.', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'SERVER2008X64\Administrator', @job_id = @jobId OUTPUTIF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackDeclare @CPUCount int=1Declare @Cmd NVARCHAR(max)SELECT @CPUCount = cpu_count/2 from sys.dm_os_sys_info;-- Change to 4 if Intel's Hyper-threading is enabled in BIOSSET @Cmd=N'sp_configure ''show advanced options'', 1;GORECONFIGURE WITH OVERRIDE;GOsp_configure ''max degree of parallelism'', '+cast(@CPUCount as nvarchar(11))+'GORECONFIGURE WITH OVERRIDE;GO'EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'SetParallelToHalf', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=@Cmd, @database_name=N'master', @flags=0IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'At 1AM', @enabled=1, @freq_type=4, @freq_interval=1, @freq_subday_type=1, @freq_subday_interval=0, @freq_relative_interval=0, @freq_recurrence_factor=0, @active_start_date=20110627, @active_end_date=99991231, @active_start_time=10000, @active_end_time=235959, @schedule_uid=N'40a4c2b4-56fa-4a0b-a22a-f0bb15788540'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackCOMMIT TRANSACTIONGOTO EndSaveQuitWithRollback: IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTIONEndSave:GOAfter the above is executed, you will see these jobs listed in SQL Server Management Studio. You may further modify them as needed.
Reference Material