Skip to content

Commit e26c03d

Browse files
committed
Tweaking the thread usage stuff
This commit has the following changes: * I changed the way I get thread time to assign it to a single variable and pass that to the dynamic SQL to prevent needing to update the temp table later (this was explained in an earlier commit) * Checks to make sure the `total_cpu_usage` column exists in `sys.dm_os_schedulers` before executing * Adds an informational message to "headline news" section letting people on <2016 instances know why thread time is 0
1 parent 632ec5c commit e26c03d

File tree

1 file changed

+94
-56
lines changed

1 file changed

+94
-56
lines changed

sp_BlitzFirst.sql

Lines changed: 94 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ DECLARE @StringToExecute NVARCHAR(MAX),
139139
@UnquotedOutputDatabaseName NVARCHAR(256) = @OutputDatabaseName ,
140140
@UnquotedOutputSchemaName NVARCHAR(256) = @OutputSchemaName ,
141141
@LocalServerName NVARCHAR(128) = CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(128)),
142-
@dm_exec_query_statistics_xml BIT = 0;
142+
@dm_exec_query_statistics_xml BIT = 0,
143+
@total_cpu_usage BIT = 0,
144+
@get_thread_time_ms NVARCHAR(MAX) = N'',
145+
@thread_time_ms FLOAT = 0;
143146

144147
/* Sanitize our inputs */
145148
SELECT
@@ -293,6 +296,36 @@ BEGIN
293296
@FinishSampleTimeWaitFor = DATEADD(ss, @Seconds, GETDATE());
294297

295298

299+
IF EXISTS
300+
(
301+
302+
SELECT
303+
1/0
304+
FROM sys.all_columns AS ac
305+
WHERE ac.object_id = OBJECT_ID('sys.dm_os_schedulers')
306+
AND ac.name = 'total_cpu_usage_ms'
307+
308+
)
309+
BEGIN
310+
311+
SELECT
312+
@total_cpu_usage = 1,
313+
@get_thread_time_ms +=
314+
N'
315+
SELECT
316+
@thread_time_ms =
317+
CONVERT
318+
(
319+
FLOAT,
320+
SUM(s.total_cpu_usage_ms)
321+
)
322+
FROM sys.dm_os_schedulers AS s
323+
WHERE s.status = ''VISIBLE ONLINE''
324+
AND s.is_online = 1;
325+
';
326+
327+
END
328+
296329
RAISERROR('Now starting diagnostic analysis',10,1) WITH NOWAIT;
297330

298331
/*
@@ -1302,6 +1335,14 @@ BEGIN
13021335
END;
13031336

13041337

1338+
IF @total_cpu_usage = 1
1339+
BEGIN
1340+
EXEC sys.sp_executesql
1341+
@get_thread_time_ms,
1342+
N'@thread_time_ms FLOAT OUTPUT',
1343+
@thread_time_ms OUTPUT;
1344+
END
1345+
13051346
/* Populate #FileStats, #PerfmonStats, #WaitStats with DMV data.
13061347
After we finish doing our checks, we'll take another sample and compare them. */
13071348
RAISERROR('Capturing first pass of wait stats, perfmon counters, file stats',10,1) WITH NOWAIT;
@@ -1315,18 +1356,7 @@ BEGIN
13151356
CASE @Seconds
13161357
WHEN 0
13171358
THEN 0
1318-
ELSE
1319-
(
1320-
SELECT
1321-
CONVERT
1322-
(
1323-
FLOAT,
1324-
SUM(s.total_cpu_usage_ms)
1325-
)
1326-
FROM sys.dm_os_schedulers AS s
1327-
WHERE s.status = ''VISIBLE ONLINE''
1328-
AND s.is_online = 1
1329-
)
1359+
ELSE @thread_time_ms
13301360
END AS thread_time_ms,
13311361
SUM(x.sum_signal_wait_time_ms) AS sum_signal_wait_time_ms,
13321362
SUM(x.sum_waiting_tasks) AS sum_waiting_tasks
@@ -1368,12 +1398,14 @@ BEGIN
13681398
GROUP BY x.Pass, x.SampleTime, x.wait_type
13691399
ORDER BY sum_wait_time_ms DESC;'
13701400

1371-
EXEC sp_executesql
1372-
@StringToExecute,
1373-
N'@StartSampleTime DATETIMEOFFSET,
1374-
@Seconds INT',
1375-
@StartSampleTime,
1376-
@Seconds;
1401+
EXEC sys.sp_executesql
1402+
@StringToExecute,
1403+
N'@StartSampleTime DATETIMEOFFSET,
1404+
@Seconds INT,
1405+
@thread_time_ms FLOAT',
1406+
@StartSampleTime,
1407+
@Seconds,
1408+
@thread_time_ms;
13771409

13781410
WITH w AS
13791411
(
@@ -1386,21 +1418,11 @@ BEGIN
13861418
)
13871419
FROM #WaitStats AS ws
13881420
WHERE Pass = 1
1389-
),
1390-
m AS
1391-
(
1392-
SELECT
1393-
max_thread =
1394-
MAX(ws.thread_time_ms)
1395-
FROM #WaitStats AS ws
1396-
WHERE Pass = 1
13971421
)
13981422
UPDATE ws
1399-
SET ws.thread_time_ms =
1400-
m.max_thread + w.total_waits
1423+
SET ws.thread_time_ms += w.total_waits
14011424
FROM #WaitStats AS ws
14021425
CROSS JOIN w
1403-
CROSS JOIN m
14041426
WHERE ws.Pass = 1
14051427
OPTION(RECOMPILE);
14061428

@@ -2509,6 +2531,13 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
25092531
WAITFOR TIME @FinishSampleTimeWaitFor;
25102532
END;
25112533

2534+
IF @total_cpu_usage = 1
2535+
BEGIN
2536+
EXEC sys.sp_executesql
2537+
@get_thread_time_ms,
2538+
N'@thread_time_ms FLOAT OUTPUT',
2539+
@thread_time_ms OUTPUT;
2540+
END
25122541

25132542
RAISERROR('Capturing second pass of wait stats, perfmon counters, file stats',10,1) WITH NOWAIT;
25142543
/* Populate #FileStats, #PerfmonStats, #WaitStats with DMV data. In a second, we'll compare these. */
@@ -2519,17 +2548,7 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
25192548
x.SampleTime,
25202549
x.wait_type,
25212550
SUM(x.sum_wait_time_ms) AS sum_wait_time_ms,
2522-
(
2523-
SELECT
2524-
CONVERT
2525-
(
2526-
FLOAT,
2527-
SUM(s.total_cpu_usage_ms)
2528-
)
2529-
FROM sys.dm_os_schedulers AS s
2530-
WHERE s.status = ''VISIBLE ONLINE''
2531-
AND s.is_online = 1
2532-
) AS thread_time_ms,
2551+
@thread_time_ms AS thread_time_ms,
25332552
SUM(x.sum_signal_wait_time_ms) AS sum_signal_wait_time_ms,
25342553
SUM(x.sum_waiting_tasks) AS sum_waiting_tasks
25352554
FROM (
@@ -2570,10 +2589,14 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
25702589
GROUP BY x.Pass, x.SampleTime, x.wait_type
25712590
ORDER BY sum_wait_time_ms DESC;';
25722591

2573-
EXEC sp_executesql
2574-
@StringToExecute,
2575-
N'@Seconds INT',
2576-
@Seconds;
2592+
EXEC sys.sp_executesql
2593+
@StringToExecute,
2594+
N'@StartSampleTime DATETIMEOFFSET,
2595+
@Seconds INT,
2596+
@thread_time_ms FLOAT',
2597+
@StartSampleTime,
2598+
@Seconds,
2599+
@thread_time_ms;
25772600

25782601
WITH w AS
25792602
(
@@ -2586,21 +2609,11 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
25862609
)
25872610
FROM #WaitStats AS ws
25882611
WHERE Pass = 2
2589-
),
2590-
m AS
2591-
(
2592-
SELECT
2593-
max_thread =
2594-
MAX(ws.thread_time_ms)
2595-
FROM #WaitStats AS ws
2596-
WHERE Pass = 2
25972612
)
25982613
UPDATE ws
2599-
SET ws.thread_time_ms =
2600-
m.max_thread + w.total_waits
2614+
SET ws.thread_time_ms += w.total_waits
26012615
FROM #WaitStats AS ws
26022616
CROSS JOIN w
2603-
CROSS JOIN m
26042617
WHERE ws.Pass = 2
26052618
OPTION(RECOMPILE);
26062619

@@ -3401,6 +3414,31 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
34013414

34023415
END; /* IF @Seconds >= 30 */
34033416

3417+
IF /* Let people on <2016 know about the thread time column */
3418+
(
3419+
@Seconds > 0
3420+
AND @total_cpu_usage = 0
3421+
)
3422+
BEGIN
3423+
INSERT INTO
3424+
#BlitzFirstResults
3425+
(
3426+
CheckID,
3427+
Priority,
3428+
FindingsGroup,
3429+
Finding,
3430+
Details,
3431+
URL
3432+
)
3433+
SELECT
3434+
48,
3435+
254,
3436+
N'Informational',
3437+
N'Thread Time will always be 0 in versions prior to SQL Server 2016',
3438+
N'sys.dm_os_schedulers doesn''t have total_cpu_usage_ms',
3439+
N'https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-schedulers-transact-sql'
3440+
3441+
END /* Let people on <2016 know about the thread time column */
34043442

34053443
/* If we didn't find anything, apologize. */
34063444
IF NOT EXISTS (SELECT * FROM #BlitzFirstResults WHERE Priority < 250)

0 commit comments

Comments
 (0)