Labels

Wednesday, 13 November 2019

How to get MAXDOP setting recommendations using SQL Query

MAXDOP setting recommendations : 

DECLARE @hyperthreadingRatio BIT;
DECLARE @logicalCPUs INT;
DECLARE @HTEnabled INT;
DECLARE @physicalCPU INT;
DECLARE @SOCKET INT;
DECLARE @logicalCPUPerNuma INT;
DECLARE @NoOfNUMA INT;

SELECT @logicalCPUs = cpu_count -- [Logical CPU Count]
 ,@hyperthreadingRatio = hyperthread_ratio --  [Hyperthread Ratio]
 ,@physicalCPU = cpu_count / hyperthread_ratio -- [Physical CPU Count]
 ,@HTEnabled = CASE WHEN cpu_count > hyperthread_ratio THEN 1 ELSE 0 END -- HTEnabled
FROM sys.dm_os_sys_info
OPTION (RECOMPILE);

SELECT @logicalCPUPerNuma = Count(parent_node_id)
-- [NumberOfLogicalProcessorsPerNuma]
FROM sys.dm_os_schedulers
WHERE [status] = 'VISIBLE ONLINE'
 AND parent_node_id < 64
GROUP BY parent_node_id
OPTION (RECOMPILE);

SELECT @NoOfNUMA = Count(DISTINCT parent_node_id)
FROM sys.dm_os_schedulers -- find NO OF NUMA Nodes 
WHERE [status] = 'VISIBLE ONLINE'
 AND parent_node_id < 64

-- Report the recommendations ....
SELECT
 --- 8 or less processors and NO HT enabled
 CASE WHEN @logicalCPUs < 8
   AND @HTEnabled = 0 THEN 'MAXDOP setting should be : ' 
+ Cast(@logicalCPUs AS VARCHAR(3))
    --- 8 or more processors and NO HT enabled
  WHEN @logicalCPUs >= 8
   AND @HTEnabled = 0 THEN 'MAXDOP setting should be : 8'
    --- 8 or more processors and HT enabled and NO NUMA
  WHEN @logicalCPUs >= 8
   AND @HTEnabled = 1
   AND @NoOfNUMA = 1 THEN 'MaxDop setting should be : ' 
+ Cast(@logicalCPUPerNuma / @physicalCPU AS VARCHAR(3))
    --- 8 or more processors and HT enabled and NUMA
  WHEN @logicalCPUs >= 8
   AND @HTEnabled = 1
   AND @NoOfNUMA > 1 THEN 'MaxDop setting should be : ' 
+ Cast(@logicalCPUPerNuma / @physicalCPU AS VARCHAR(3)) ELSE '' END AS Recommendations;

Generate table definition to match query results

I used to do below code during code tuning like instead of loading data into temp table from select statement directly I used to create temp table structure from the table or query results by passing into @query variable and then use insert into temp table for select query results.

SET NOCOUNT ON;

DECLARE @Query VARCHAR(MAX) = 'select * from dbname.schemaname.tablename;';
DECLARE @TempTableName VARCHAR(128) = '#temptable'
DECLARE @ColumnList VARCHAR(MAX);

SELECT @ColumnList = STUFF((
   SELECT '    , ' + name + ' ' + system_type_name + ' ' 
+ CASE is_nullable WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END + CHAR(10)
   FROM sys.dm_exec_describe_first_result_set(@Query, NULL, 0)
   FOR XML PATH('')
   ), 1, 1, '');

PRINT 'CREATE TABLE ' + @TempTableName + '('
PRINT @ColumnList;
PRINT (');');