|
| 1 | +/* |
| 2 | +-- +----------------------------------------------------------------------------+ |
| 3 | +-- | DBA Mastery | |
| 4 | +-- | dbamastery@outlook.com | |
| 5 | +-- | http://www.dbamastery.com | |
| 6 | +-- |----------------------------------------------------------------------------| |
| 7 | +-- | | |
| 8 | +-- |----------------------------------------------------------------------------| |
| 9 | +-- | DATABASE : SQL Server | |
| 10 | +-- | FILE : maxdop_calculator.sql | |
| 11 | +-- | CLASS : Performance tuning | |
| 12 | +-- | PURPOSE : Calculates the optimal value for MAXDOP (> SQL 2016 ) | |
| 13 | +-- | | |
| 14 | +-- | NOTE : As with any code, ensure to test this script in a development | |
| 15 | +-- | environment before attempting to run it in production. | |
| 16 | +-- | | |
| 17 | +-- | Based on Microsoft KB# 2806535: https://goo.gl/4FD9BH and | |
| 18 | +-- | MSDN MaxDOP calculator: https://goo.gl/hzyxY1 | |
| 19 | +-- +----------------------------------------------------------------------------+ |
| 20 | +Copyright (c) 2019 DBA Mastery |
| 21 | +
|
| 22 | +Permission is hereby granted, free of charge, to any person obtaining a copy |
| 23 | +of this software and associated documentation files (the "Software"), to deal |
| 24 | +in the Software without restriction, including without limitation the rights |
| 25 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 26 | +copies of the Software, and to permit persons to whom the Software is |
| 27 | +furnished to do so, subject to the following conditions: |
| 28 | +
|
| 29 | +The above copyright notice and this permission notice shall be included in all |
| 30 | +copies or substantial portions of the Software. |
| 31 | +
|
| 32 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 33 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 34 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 35 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 36 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 37 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 38 | +SOFTWARE. |
| 39 | +*/ |
| 40 | + |
| 41 | +SET NOCOUNT ON; |
| 42 | +USE MASTER; |
| 43 | + |
| 44 | +-- Dropping temp table in case it exists |
| 45 | +IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects o WHERE o.XTYPE IN ('U') AND o.id = object_id(N'tempdb..#MaxDOPDB')) |
| 46 | + DROP TABLE #MaxDOPDB; |
| 47 | + |
| 48 | +DECLARE @SQLVersion INT, @NumaNodes INT, @NumCPUs INT, @MaxDop SQL_VARIANT, @RecommendedMaxDop INT; |
| 49 | + |
| 50 | +-- Getting SQL Server version |
| 51 | +SELECT @SQLVersion = SUBSTRING(CONVERT(VARCHAR, SERVERPROPERTY('ProductVersion')), 1, 2); |
| 52 | + |
| 53 | +-- Getting number of NUMA nodes |
| 54 | +SELECT @NumaNodes = COUNT(DISTINCT memory_node_id) FROM sys.dm_os_memory_clerks WHERE memory_node_id != 64; |
| 55 | + |
| 56 | +-- Getting number of CPUs (cores) |
| 57 | +SELECT @NumCPUs = COUNT(scheduler_id) FROM sys.dm_os_schedulers WHERE status = 'VISIBLE ONLINE'; |
| 58 | + |
| 59 | +-- Getting current MAXDOP at instance level |
| 60 | +SELECT @MaxDop = value_in_use FROM sys.configurations WHERE name = 'max degree of parallelism'; |
| 61 | + |
| 62 | +-- MAXDOP calculation (Instance level) |
| 63 | +-- If SQL Server has a single NUMA node |
| 64 | +IF @NumaNodes = 1 |
| 65 | +BEGIN |
| 66 | + IF @NumCPUs < 8 |
| 67 | + -- If the number of logical processors is less than 8, MAXDOP equals the number of logical processors |
| 68 | + SET @RecommendedMaxDop = @NumCPUs; |
| 69 | + ELSE |
| 70 | + -- Keep MAXDOP at 8 |
| 71 | + SET @RecommendedMaxDop = 8; |
| 72 | +END; |
| 73 | +ELSE |
| 74 | +BEGIN |
| 75 | + -- If SQL Server has multiple NUMA nodes |
| 76 | + IF (@NumCPUs / @NumaNodes) < 8 |
| 77 | + -- If the number of logical processors per NUMA node is less than 8, MAXDOP equals or below logical processors per NUMA node |
| 78 | + SET @RecommendedMaxDop = (@NumCPUs / @NumaNodes); |
| 79 | + ELSE |
| 80 | + -- If greater than 8 logical processors per NUMA node - Keep MAXDOP at 8 |
| 81 | + SET @RecommendedMaxDop = 8; |
| 82 | +END; |
| 83 | + |
| 84 | +-- If SQL Server is > 2016 |
| 85 | +IF CONVERT(INT, @SQLVersion) > 12 |
| 86 | +BEGIN |
| 87 | + -- Getting current MAXDOP at database level |
| 88 | + |
| 89 | + -- Creating temp table |
| 90 | + CREATE TABLE #MaxDOPDB |
| 91 | + ( |
| 92 | + DBName sysname, |
| 93 | + configuration_id INT, |
| 94 | + name NVARCHAR(120), |
| 95 | + value_for_primary SQL_VARIANT, |
| 96 | + value_for_secondary SQL_VARIANT |
| 97 | + ); |
| 98 | + |
| 99 | + INSERT INTO #MaxDOPDB |
| 100 | + EXEC sp_msforeachdb 'USE [?]; SELECT DB_NAME(), configuration_id, name, value, value_for_secondary FROM sys.database_scoped_configurations WHERE name = ''MAXDOP'''; |
| 101 | + |
| 102 | + -- Displaying database MAXDOP configuration |
| 103 | + PRINT '------------------------------------------------------------------------'; |
| 104 | + PRINT 'MAXDOP at Database level:'; |
| 105 | + PRINT '------------------------------------------------------------------------'; |
| 106 | + SELECT CONVERT(VARCHAR(30), dbname) AS DatabaseName, CONVERT(VARCHAR(10), name) AS ConfigurationName, CONVERT(INT, value_for_primary) AS "MAXDOP Configured Value" |
| 107 | + FROM #MaxDOPDB |
| 108 | + WHERE dbname NOT IN ('master', 'msdb', 'tempdb', 'model'); |
| 109 | + PRINT ''; |
| 110 | + |
| 111 | + -- Displaying current and recommended MAXDOP |
| 112 | + PRINT '--------------------------------------------------------------'; |
| 113 | + PRINT 'MAXDOP at Instance level:'; |
| 114 | + PRINT '--------------------------------------------------------------'; |
| 115 | + PRINT 'MAXDOP configured value: ' + CHAR(9) + CAST(@MaxDop AS CHAR); |
| 116 | + PRINT 'MAXDOP recommended value: ' + CHAR(9) + CAST(@RecommendedMaxDop AS CHAR); |
| 117 | + PRINT '--------------------------------------------------------------'; |
| 118 | + PRINT ''; |
| 119 | + |
| 120 | + IF (@MaxDop <> @RecommendedMaxDop) |
| 121 | + BEGIN |
| 122 | + PRINT 'In case you want to change MAXDOP to the recommended value, please use this script:'; |
| 123 | + PRINT ''; |
| 124 | + PRINT 'EXEC sp_configure ''max degree of parallelism'', ' + CAST(@RecommendedMaxDop AS CHAR); |
| 125 | + PRINT 'GO'; |
| 126 | + PRINT 'RECONFIGURE WITH OVERRIDE;'; |
| 127 | + END; |
| 128 | +END; |
| 129 | +ELSE |
| 130 | +BEGIN |
| 131 | + -- Displaying current and recommended MAXDOP |
| 132 | + PRINT '--------------------------------------------------------------'; |
| 133 | + PRINT 'MAXDOP at Instance level:'; |
| 134 | + PRINT '--------------------------------------------------------------'; |
| 135 | + PRINT 'MAXDOP configured value: ' + CHAR(9) + CAST(@MaxDop AS CHAR); |
| 136 | + PRINT 'MAXDOP recommended value: ' + CHAR(9) + CAST(@RecommendedMaxDop AS CHAR); |
| 137 | + PRINT '--------------------------------------------------------------'; |
| 138 | + PRINT ''; |
| 139 | + |
| 140 | + IF (@MaxDop <> @RecommendedMaxDop) |
| 141 | + BEGIN |
| 142 | + PRINT 'In case you want to change MAXDOP to the recommended value, please use this script:'; |
| 143 | + PRINT ''; |
| 144 | + PRINT 'EXEC sp_configure ''max degree of parallelism'', ' + CAST(@RecommendedMaxDop AS CHAR); |
| 145 | + PRINT 'GO'; |
| 146 | + PRINT 'RECONFIGURE WITH OVERRIDE;'; |
| 147 | + END; |
| 148 | +END; |
0 commit comments