diff --git a/Helper Views/WhatsUpMemory.sql b/Helper Views/WhatsUpMemory.sql index ac8ced7..41c0c38 100644 --- a/Helper Views/WhatsUpMemory.sql +++ b/Helper Views/WhatsUpMemory.sql @@ -81,7 +81,7 @@ FROM sys.dm_os_buffer_descriptors AS obd INNER HASH JOIN ( SELECT - schema_name = + schema_name = s.name, object_name = o.name, @@ -106,7 +106,7 @@ INNER HASH JOIN UNION ALL SELECT - schema_name = + schema_name = s.name, object_name = o.name, @@ -131,7 +131,7 @@ INNER HASH JOIN UNION ALL SELECT - schema_name = + schema_name = s.name, object_name = o.name, @@ -158,5 +158,5 @@ GROUP BY x.schema_name, x.object_name, x.index_name -ORDER BY - COUNT_BIG(*) DESC; \ No newline at end of file +ORDER BY + COUNT_BIG(*) DESC; diff --git a/Install-All/DarlingData.sql b/Install-All/DarlingData.sql index ef14d06..4af657f 100644 --- a/Install-All/DarlingData.sql +++ b/Install-All/DarlingData.sql @@ -1,4 +1,4 @@ --- Compile Date: 06/28/2024 19:44:07 UTC +-- Compile Date: 08/27/2024 03:33:48 UTC SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; @@ -11178,6 +11178,7 @@ BEGIN OR el.text LIKE N'The client was unable to reuse a session with%' OR el.text LIKE N'SSPI%' OR el.text LIKE N'%Severity: 1[0-8]%' + OR el.text LIKE N'Login succeeded for user%' OR el.text IN ( N'The Database Mirroring endpoint is in disabled or stopped state.', @@ -13487,8 +13488,6 @@ OPTION(MAXDOP 1, RECOMPILE);', ) / 2 ) + 1 ) - FROM sys.dm_exec_requests AS der - WHERE der.session_id = deqmg.session_id FOR XML PATH(''''), TYPE @@ -13499,7 +13498,25 @@ OPTION(MAXDOP 1, RECOMPILE);', CASE WHEN @skip_plan_xml = 0 THEN N' - deqp.query_plan,' + + query_plan = + CASE + WHEN TRY_CAST(deqp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(deqp.query_plan AS xml) + WHEN TRY_CAST(deqp.query_plan AS xml) IS NULL + THEN + ( + SELECT + [processing-instruction(query_plan)] = + N''-- '' + NCHAR(13) + NCHAR(10) + + N''-- This is a huge query plan.'' + NCHAR(13) + NCHAR(10) + + N''-- Remove the headers and footers, save it as a .sqlplan file, and re-open it.'' + NCHAR(13) + NCHAR(10) + + NCHAR(13) + NCHAR(10) + + REPLACE(deqp.query_plan, N'' 'total waits' +BEGIN + SELECT + @current_table = 'inserting #plan_ids_with_total_waits', + @sql = @isolation_level; + + IF @troubleshoot_performance = 1 + BEGIN + EXEC sys.sp_executesql + @troubleshoot_insert, + N'@current_table nvarchar(100)', + @current_table; + + SET STATISTICS XML ON; + END; + + SELECT + @sql += N' + SELECT TOP (@top) + @database_id, + qsrs.plan_id, + MAX(qsws.total_query_wait_time_ms) AS total_query_wait_time_ms + FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs + JOIN ' + @database_name_quoted + N'.sys.query_store_wait_stats AS qsws + ON qsrs.plan_id = qsws.plan_id + WHERE 1 = 1 + AND qsws.wait_category = ' + + CASE @sort_order + WHEN 'cpu waits' THEN N'1' + WHEN 'lock waits' THEN N'3' + WHEN 'locks waits' THEN N'3' + WHEN 'latch waits' THEN N'4' + WHEN 'latches waits' THEN N'4' + WHEN 'buffer latch waits' THEN N'5' + WHEN 'buffer latches waits' THEN N'5' + WHEN 'buffer io waits' THEN N'6' + WHEN 'log waits' THEN N'14' + WHEN 'log io waits' THEN N'14' + WHEN 'network waits' THEN N'15' + WHEN 'network io waits' THEN N'15' + WHEN 'parallel waits' THEN N'16' + WHEN 'parallelism waits' THEN N'16' + WHEN 'memory waits' THEN N'17' + END + + @where_clause + + N' + GROUP + BY qsrs.plan_id + ORDER BY + MAX(qsws.total_query_wait_time_ms) DESC + OPTION(RECOMPILE, OPTIMIZE FOR (@top = 9223372036854775807));' + @nc10; + + IF @debug = 1 + BEGIN + PRINT LEN(@sql); + PRINT @sql; + END; + + INSERT + #plan_ids_with_total_waits WITH(TABLOCK) + ( + database_id, + plan_id, + total_query_wait_time_ms + ) + EXEC sys.sp_executesql + @sql, + @parameters, + @top, + @start_date, + @end_date, + @execution_count, + @duration_ms, + @execution_type_desc, + @database_id, + @queries_top, + @work_start_utc, + @work_end_utc; + + IF @troubleshoot_performance = 1 + BEGIN + SET STATISTICS XML OFF; + + EXEC sys.sp_executesql + @troubleshoot_update, + N'@current_table nvarchar(100)', + @current_table; + + EXEC sys.sp_executesql + @troubleshoot_info, + N'@sql nvarchar(max), + @current_table nvarchar(100)', + @sql, + @current_table; + END; +END; +/*End populating sort-helping tables*/ + +/* +This gets the plan_ids we care about. + +We unfortunately need an ELSE IF chain here +because the final branch contains defaults +that we only want to hit if we did not hit +any others. */ SELECT @current_table = 'inserting #distinct_plans', @@ -18707,32 +19163,55 @@ BEGIN SET STATISTICS XML ON; END; -SELECT - @sql += N' -SELECT TOP (@top) - qsrs.plan_id -FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs -WHERE 1 = 1 -' + @where_clause - + N' -GROUP - BY qsrs.plan_id -ORDER BY - MAX(' + -CASE @sort_order - WHEN 'cpu' THEN N'qsrs.avg_cpu_time' - WHEN 'logical reads' THEN N'qsrs.avg_logical_io_reads' - WHEN 'physical reads' THEN N'qsrs.avg_physical_io_reads' - WHEN 'writes' THEN N'qsrs.avg_logical_io_writes' - WHEN 'duration' THEN N'qsrs.avg_duration' - WHEN 'memory' THEN N'qsrs.avg_query_max_used_memory' - WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used' ELSE N'qsrs.avg_cpu_time' END - WHEN 'executions' THEN N'qsrs.count_executions' - WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time' -END + -N') DESC -OPTION(RECOMPILE, OPTIMIZE FOR (@top = 9223372036854775807));' + @nc10; +IF @sort_order = 'plan count by hashes' +BEGIN + SELECT + @sql += N' + SELECT DISTINCT + plan_id + FROM #plan_ids_with_query_hashes + WHERE database_id = @database_id + OPTION(RECOMPILE);' + @nc10; +END +ELSE IF @sort_order_is_a_wait = 1 +BEGIN + SELECT + @sql += N' + SELECT DISTINCT + plan_id + FROM #plan_ids_with_total_waits + WHERE database_id = @database_id + OPTION(RECOMPILE);' + @nc10; +END +ELSE +BEGIN + SELECT + @sql += N' + SELECT TOP (@top) + qsrs.plan_id + FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs + WHERE 1 = 1 + ' + @where_clause + + N' + GROUP + BY qsrs.plan_id + ORDER BY + MAX(' + + CASE @sort_order + WHEN 'cpu' THEN N'qsrs.avg_cpu_time' + WHEN 'logical reads' THEN N'qsrs.avg_logical_io_reads' + WHEN 'physical reads' THEN N'qsrs.avg_physical_io_reads' + WHEN 'writes' THEN N'qsrs.avg_logical_io_writes' + WHEN 'duration' THEN N'qsrs.avg_duration' + WHEN 'memory' THEN N'qsrs.avg_query_max_used_memory' + WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used' ELSE N'qsrs.avg_cpu_time' END + WHEN 'executions' THEN N'qsrs.count_executions' + WHEN 'recent' THEN N'qsrs.last_execution_time' + ELSE N'qsrs.avg_cpu_time' + END + + N') DESC + OPTION(RECOMPILE, OPTIMIZE FOR (@top = 9223372036854775807));' + @nc10; +END; IF @debug = 1 BEGIN @@ -18884,7 +19363,26 @@ CROSS APPLY ( SELECT TOP (@queries_top) qsrs.* - FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs + FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs' + IF @sort_order = 'plan count by hashes' + BEGIN + SELECT + @sql += N' + JOIN #plan_ids_with_query_hashes AS hashes + ON qsrs.plan_id = hashes.plan_id + AND hashes.database_id = @database_id' + END; + IF @sort_order_is_a_wait = 1 + BEGIN + SELECT + @sql += N' + JOIN #plan_ids_with_total_waits AS waits + ON qsrs.plan_id = waits.plan_id + AND waits.database_id = @database_id' + END; + +SELECT + @sql += N' WHERE qsrs.plan_id = dp.plan_id AND 1 = 1 ' + @where_clause @@ -18900,7 +19398,8 @@ CASE @sort_order WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used' ELSE N'qsrs.avg_cpu_time' END WHEN 'executions' THEN N'qsrs.count_executions' WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time' + WHEN 'plan count by hashes' THEN N'hashes.plan_hash_count_for_query_hash DESC, hashes.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'waits.total_query_wait_time_ms' ELSE N'qsrs.avg_cpu_time' END END + N' DESC ) AS qsrs GROUP BY @@ -20321,6 +20820,8 @@ BEGIN #maintenance_plans; TRUNCATE TABLE #query_text_search; + TRUNCATE TABLE + #query_text_search_not; TRUNCATE TABLE #dm_exec_query_stats; TRUNCATE TABLE @@ -20416,9 +20917,9 @@ FROM qsqt.query_sql_text, query_plan = CASE - WHEN TRY_CAST(qsp.query_plan AS XML) IS NOT NULL - THEN TRY_CAST(qsp.query_plan AS XML) - WHEN TRY_CAST(qsp.query_plan AS XML) IS NULL + WHEN TRY_CAST(qsp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(qsp.query_plan AS xml) + WHEN TRY_CAST(qsp.query_plan AS xml) IS NULL THEN ( SELECT @@ -20473,11 +20974,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.first_execution_time + SWITCHOFFSET + ( + qsrs.first_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -20488,11 +20988,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.last_execution_time + SWITCHOFFSET + ( + qsrs.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -20589,9 +21088,25 @@ FROM WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used_mb' ELSE N'qsrs.avg_cpu_time' END WHEN 'executions' THEN N'qsrs.count_executions' WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time_ms' + WHEN 'plan count by hashes' THEN N'hashes.plan_hash_count_for_query_hash DESC, hashes.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'waits.total_query_wait_time_ms' ELSE N'qsrs.avg_cpu_time' END END + N' DESC )' + /* + Bolt any special sorting columns on, because we need them to + be in scope for sorting. + Has the side-effect of making them visible in the final output, + because our SELECT is just x.*. + + But, really, is having the columns visible in the output a bad thing? + I find it's helpful. + */ + + CASE WHEN @sort_order = 'plan count by hashes' + THEN N' , hashes.plan_hash_count_for_query_hash, hashes.query_hash' + WHEN @sort_order_is_a_wait = 1 + THEN N' , waits.total_query_wait_time_ms AS total_wait_time_from_sort_order_ms' + ELSE N'' + END ) ); END; /*End expert mode 1, format output 0 columns*/ @@ -20641,9 +21156,9 @@ FROM qsqt.query_sql_text, query_plan = CASE - WHEN TRY_CAST(qsp.query_plan AS XML) IS NOT NULL - THEN TRY_CAST(qsp.query_plan AS XML) - WHEN TRY_CAST(qsp.query_plan AS XML) IS NULL + WHEN TRY_CAST(qsp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(qsp.query_plan AS xml) + WHEN TRY_CAST(qsp.query_plan AS xml) IS NULL THEN ( SELECT @@ -20701,11 +21216,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.first_execution_time + SWITCHOFFSET + ( + qsrs.first_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -20716,11 +21230,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.last_execution_time + SWITCHOFFSET + ( + qsrs.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -20818,9 +21331,26 @@ FROM WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used_mb' ELSE N'qsrs.avg_cpu_time' END WHEN 'executions' THEN N'qsrs.count_executions' WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time_ms' + WHEN 'plan count by hashes' THEN N'hashes.plan_hash_count_for_query_hash DESC, hashes.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'waits.total_query_wait_time_ms' ELSE N'qsrs.avg_cpu_time' END END + N' DESC )' + /* + Bolt any special sorting columns on, because we need them to + be in scope for sorting. + Has the side-effect of making them visible in the final output, + because our SELECT is just x.*. + + But, really, is having the columns visible in the output a bad thing? + I find it's helpful, but it does mean that we have to format them + when applicable. + */ + + CASE WHEN @sort_order = 'plan count by hashes' + THEN N' , FORMAT(hashes.plan_hash_count_for_query_hash, ''N0'') AS plan_hash_count_for_query_hash, hashes.query_hash' + WHEN @sort_order_is_a_wait = 1 + THEN N' , FORMAT(waits.total_query_wait_time_ms, ''N0'') AS total_wait_time_from_sort_order_ms' + ELSE N'' + END ) ); END; /*End expert mode = 1, format output = 1*/ @@ -20870,9 +21400,9 @@ FROM qsqt.query_sql_text, query_plan = CASE - WHEN TRY_CAST(qsp.query_plan AS XML) IS NOT NULL - THEN TRY_CAST(qsp.query_plan AS XML) - WHEN TRY_CAST(qsp.query_plan AS XML) IS NULL + WHEN TRY_CAST(qsp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(qsp.query_plan AS xml) + WHEN TRY_CAST(qsp.query_plan AS xml) IS NULL THEN ( SELECT @@ -20927,11 +21457,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.first_execution_time + SWITCHOFFSET + ( + qsrs.first_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -20942,11 +21471,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.last_execution_time + SWITCHOFFSET + ( + qsrs.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -21021,9 +21549,25 @@ FROM WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used_mb' ELSE N'qsrs.avg_cpu_time' END WHEN 'executions' THEN N'qsrs.count_executions' WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time_ms' + WHEN 'plan count by hashes' THEN N'hashes.plan_hash_count_for_query_hash DESC, hashes.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'waits.total_query_wait_time_ms' ELSE N'qsrs.avg_cpu_time' END END + N' DESC )' + /* + Bolt any special sorting columns on, because we need them to + be in scope for sorting. + Has the side-effect of making them visible in the final output, + because our SELECT is just x.*. + + But, really, is having the columns visible in the output a bad thing? + I find it's helpful. + */ + + CASE WHEN @sort_order = 'plan count by hashes' + THEN N' , hashes.plan_hash_count_for_query_hash, hashes.query_hash' + WHEN @sort_order_is_a_wait = 1 + THEN N' , waits.total_query_wait_time_ms AS total_wait_time_from_sort_order_ms' + ELSE N'' + END ) ); END; /*End expert mode = 0, format output = 0*/ @@ -21074,9 +21618,9 @@ FROM qsqt.query_sql_text, query_plan = CASE - WHEN TRY_CAST(qsp.query_plan AS XML) IS NOT NULL - THEN TRY_CAST(qsp.query_plan AS XML) - WHEN TRY_CAST(qsp.query_plan AS XML) IS NULL + WHEN TRY_CAST(qsp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(qsp.query_plan AS xml) + WHEN TRY_CAST(qsp.query_plan AS xml) IS NULL THEN ( SELECT @@ -21131,11 +21675,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.first_execution_time + SWITCHOFFSET + ( + qsrs.first_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -21146,11 +21689,10 @@ FROM CASE WHEN @timezone IS NULL THEN - DATEADD - ( - MINUTE, - @utc_minutes_original, - qsrs.last_execution_time + SWITCHOFFSET + ( + qsrs.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -21225,9 +21767,26 @@ FROM WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'qsrs.avg_tempdb_space_used_mb' ELSE N'qsrs.avg_cpu_time' END WHEN 'executions' THEN N'qsrs.count_executions' WHEN 'recent' THEN N'qsrs.last_execution_time' - ELSE N'qsrs.avg_cpu_time_ms' + WHEN 'plan count by hashes' THEN N'hashes.plan_hash_count_for_query_hash DESC, hashes.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'waits.total_query_wait_time_ms' ELSE N'qsrs.avg_cpu_time' END END + N' DESC )' + /* + Bolt any special sorting columns on, because we need them to + be in scope for sorting. + Has the side-effect of making them visible in the final output, + because our SELECT is just x.*. + + But, really, is having the columns visible in the output a bad thing? + I find it's helpful, but it does mean that we have to format them + when applicable. + */ + + CASE WHEN @sort_order = 'plan count by hashes' + THEN N' , FORMAT(hashes.plan_hash_count_for_query_hash, ''N0'') AS plan_hash_count_for_query_hash, hashes.query_hash' + WHEN @sort_order_is_a_wait = 1 + THEN N' , FORMAT(waits.total_query_wait_time_ms, ''N0'') AS total_wait_time_from_sort_order_ms' + ELSE N'' + END ) ); END; /*End expert mode = 0, format output = 1*/ @@ -21241,7 +21800,31 @@ FROM ( nvarchar(MAX), N' - FROM #query_store_runtime_stats AS qsrs + FROM #query_store_runtime_stats AS qsrs' + ) + IF @sort_order = 'plan count by hashes' + BEGIN + SELECT + @sql += N' + JOIN #plan_ids_with_query_hashes AS hashes + ON qsrs.plan_id = hashes.plan_id + AND qsrs.database_id = hashes.database_id' + END; + IF @sort_order_is_a_wait = 1 + BEGIN + SELECT + @sql += N' + JOIN #plan_ids_with_total_waits AS waits + ON qsrs.plan_id = waits.plan_id + AND qsrs.database_id = waits.database_id' + END; + +SELECT + @sql += + CONVERT + ( + NVARCHAR(MAX), + N' CROSS APPLY ( SELECT @@ -21419,8 +22002,13 @@ ORDER BY ' + WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'x.avg_tempdb_space_used_mb' ELSE N'x.avg_cpu_time' END WHEN 'executions' THEN N'x.count_executions' WHEN 'recent' THEN N'x.last_execution_time' - ELSE N'x.avg_cpu_time_ms' + WHEN 'plan count by hashes' THEN N'x.plan_hash_count_for_query_hash DESC, x.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'x.total_wait_time_from_sort_order_ms' ELSE N'x.avg_cpu_time' END END + /* + The ORDER BY is on the same level as the topmost SELECT, which is just SELECT x.*. + This means that to sort formatted output, we have to un-format it. + */ WHEN 1 THEN CASE @sort_order @@ -21433,7 +22021,8 @@ ORDER BY ' + WHEN 'tempdb' THEN CASE WHEN @new = 1 THEN N'TRY_PARSE(x.avg_tempdb_space_used_mb AS money)' ELSE N'TRY_PARSE(x.avg_cpu_time AS money)' END WHEN 'executions' THEN N'TRY_PARSE(x.count_executions AS money)' WHEN 'recent' THEN N'x.last_execution_time' - ELSE N'TRY_PARSE(x.avg_cpu_time_ms AS money)' + WHEN 'plan count by hashes' THEN N'TRY_PARSE(x.plan_hash_count_for_query_hash AS money) DESC, x.query_hash' + ELSE CASE WHEN @sort_order_is_a_wait = 1 THEN N'TRY_PARSE(x.total_wait_time_from_sort_order_ms AS money)' ELSE N'TRY_PARSE(x.avg_cpu_time AS money)' END END END + N' DESC @@ -21451,9 +22040,9 @@ OPTION(RECOMPILE);' EXEC sys.sp_executesql @sql, - N'@utc_minutes_original bigint, + N'@utc_offset_string nvarchar(6), @timezone sysname', - @utc_minutes_original, + @utc_offset_string, @timezone; END; /*End runtime stats main query*/ ELSE @@ -21506,12 +22095,11 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qspf.create_time - ) + qspf.create_time, + @utc_offset_string + ) WHEN @timezone IS NOT NULL THEN qspf.create_time AT TIME ZONE @timezone END, @@ -21521,12 +22109,11 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qspf.last_updated_time - ) + qspf.last_updated_time, + @utc_offset_string + ) WHEN @timezone IS NOT NULL THEN qspf.last_updated_time AT TIME ZONE @timezone END, @@ -21634,11 +22221,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.initial_compile_start_time + qsq.initial_compile_start_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.initial_compile_start_time AT TIME ZONE @timezone @@ -21649,11 +22235,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.last_compile_start_time + qsq.last_compile_start_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.last_compile_start_time AT TIME ZONE @timezone @@ -21664,11 +22249,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.last_execution_time + qsq.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.last_execution_time AT TIME ZONE @timezone @@ -22097,11 +22681,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qspf.create_time + qspf.create_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qspf.create_time AT TIME ZONE @timezone @@ -22112,11 +22695,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qspf.last_updated_time + qspf.last_updated_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qspf.last_updated_time AT TIME ZONE @timezone @@ -22225,11 +22807,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.initial_compile_start_time + qsq.initial_compile_start_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.initial_compile_start_time AT TIME ZONE @timezone @@ -22240,11 +22821,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.last_compile_start_time + qsq.last_compile_start_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.last_compile_start_time AT TIME ZONE @timezone @@ -22255,11 +22835,10 @@ BEGIN CASE WHEN @timezone IS NULL THEN - DATEADD + SWITCHOFFSET ( - MINUTE, - @utc_minutes_original, - qsq.last_execution_time + qsq.last_execution_time, + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsq.last_execution_time AT TIME ZONE @timezone @@ -22855,6 +23434,8 @@ BEGIN @database_name, sort_order = @sort_order, + sort_order_is_a_wait = + @sort_order_is_a_wait, [top] = @top, start_date = @@ -23013,14 +23594,14 @@ BEGIN @timezone, utc_minutes_difference = @utc_minutes_difference, - utc_minutes_original = - @utc_minutes_original, - df = - @df, - work_start_utc = - @work_start_utc, - work_end_utc = - @work_end_utc; + utc_offset_string = + @utc_offset_string, + df = + @df, + work_start_utc = + @work_start_utc, + work_end_utc = + @work_end_utc; IF EXISTS ( @@ -23183,6 +23764,52 @@ BEGIN '#include_query_hashes is empty'; END; + IF EXISTS + ( + SELECT + 1/0 + FROM #plan_ids_with_query_hashes AS hashes + ) + BEGIN + SELECT + table_name = + '#plan_ids_with_query_hashes', + hashes.* + FROM #plan_ids_with_query_hashes AS hashes + ORDER BY + hashes.plan_id + OPTION(RECOMPILE); + END; + ELSE + BEGIN + SELECT + result = + '#plan_ids_with_query_hashes is empty'; + END; + + IF EXISTS + ( + SELECT + 1/0 + FROM #plan_ids_with_total_waits AS waits + ) + BEGIN + SELECT + table_name = + '#plan_ids_with_total_waits', + waits.* + FROM #plan_ids_with_total_waits AS waits + ORDER BY + waits.plan_id + OPTION(RECOMPILE); + END; + ELSE + BEGIN + SELECT + result = + '#plan_ids_with_total_waits is empty'; + END; + IF EXISTS ( SELECT diff --git a/String Functions/get_letters.sql b/String Functions/get_letters.sql index 17d69fd..9d13acb 100644 --- a/String Functions/get_letters.sql +++ b/String Functions/get_letters.sql @@ -110,7 +110,7 @@ WITH e1 (n) AS e2 (n) AS ( SELECT - 1 + 1 FROM e1 AS a CROSS JOIN e1 AS b ), diff --git a/sp_PressureDetector/sp_PressureDetector.sql b/sp_PressureDetector/sp_PressureDetector.sql index 2b165ce..9612a3e 100644 --- a/sp_PressureDetector/sp_PressureDetector.sql +++ b/sp_PressureDetector/sp_PressureDetector.sql @@ -2353,8 +2353,8 @@ OPTION(MAXDOP 1, RECOMPILE);', ) AS waits OUTER APPLY sys.dm_exec_text_query_plan ( - deqmg.plan_handle, - der.statement_start_offset, + deqmg.plan_handle, + der.statement_start_offset, der.statement_end_offset ) AS deqp OUTER APPLY sys.dm_exec_sql_text(deqmg.plan_handle) AS dest' + @@ -2896,8 +2896,8 @@ OPTION(MAXDOP 1, RECOMPILE);', OUTER APPLY sys.dm_exec_sql_text(der.plan_handle) AS dest OUTER APPLY sys.dm_exec_text_query_plan ( - der.plan_handle, - der.statement_start_offset, + der.plan_handle, + der.statement_start_offset, der.statement_end_offset ) AS deqp' + CASE diff --git a/sp_QuickieStore/sp_QuickieStore.sql b/sp_QuickieStore/sp_QuickieStore.sql index b20cb68..a34df19 100644 --- a/sp_QuickieStore/sp_QuickieStore.sql +++ b/sp_QuickieStore/sp_QuickieStore.sql @@ -1634,15 +1634,15 @@ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;', SYSUTCDATETIME() ), /* - There is no direct way to get the user's timezone in a - format compatible with sys.time_zone_info. + There is no direct way to get the user's timezone in a + format compatible with sys.time_zone_info. - We also cannot directly get their UTC offset, - so we need this hack to get it instead. + We also cannot directly get their UTC offset, + so we need this hack to get it instead. - This is to make our datetimeoffsets have the - correct offset in cases where the user didn't - give us their timezone. + This is to make our datetimeoffsets have the + correct offset in cases where the user didn't + give us their timezone. */ @utc_offset_string = RIGHT(SYSDATETIMEOFFSET(), 6), @df = @@DATEFIRST, @@ -4565,17 +4565,17 @@ BEGIN SELECT @current_table = 'inserting #plan_ids_with_query_hashes', @sql = @isolation_level; - + IF @troubleshoot_performance = 1 BEGIN EXEC sys.sp_executesql @troubleshoot_insert, N'@current_table nvarchar(100)', @current_table; - + SET STATISTICS XML ON; END; - + SELECT /* This sort order is useless if we don't show the @@ -4591,11 +4591,11 @@ BEGIN FROM ( SELECT - QueryHashesWithIds.plan_id, + QueryHashesWithIds.plan_id, QueryHashesWithCounts.query_hash, QueryHashesWithCounts.plan_hash_count_for_query_hash, DENSE_RANK() OVER (ORDER BY QueryHashesWithCounts.plan_hash_count_for_query_hash DESC, QueryHashesWithCounts.query_hash DESC) AS ranking - FROM + FROM ( SELECT qsq.query_hash, @@ -4609,7 +4609,7 @@ BEGIN ' + @where_clause + N' GROUP - BY qsq.query_hash + BY qsq.query_hash ) AS QueryHashesWithCounts JOIN ( @@ -4635,7 +4635,7 @@ BEGIN PRINT LEN(@sql); PRINT @sql; END; - + INSERT #plan_ids_with_query_hashes WITH(TABLOCK) ( @@ -4657,40 +4657,40 @@ BEGIN @queries_top, @work_start_utc, @work_end_utc; - + IF @troubleshoot_performance = 1 BEGIN SET STATISTICS XML OFF; - + EXEC sys.sp_executesql @troubleshoot_update, N'@current_table nvarchar(100)', @current_table; - + EXEC sys.sp_executesql @troubleshoot_info, N'@sql nvarchar(max), @current_table nvarchar(100)', @sql, @current_table; - END; + END; END; IF @sort_order = 'total waits' BEGIN SELECT @current_table = 'inserting #plan_ids_with_total_waits', @sql = @isolation_level; - + IF @troubleshoot_performance = 1 BEGIN EXEC sys.sp_executesql @troubleshoot_insert, N'@current_table nvarchar(100)', @current_table; - + SET STATISTICS XML ON; END; - + SELECT @sql += N' SELECT TOP (@top) @@ -4700,7 +4700,7 @@ BEGIN FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs JOIN ' + @database_name_quoted + N'.sys.query_store_wait_stats AS qsws ON qsrs.plan_id = qsws.plan_id - WHERE 1 = 1 + WHERE 1 = 1 ' + @where_clause + N' GROUP @@ -4714,7 +4714,7 @@ BEGIN PRINT LEN(@sql); PRINT @sql; END; - + INSERT #plan_ids_with_total_waits WITH(TABLOCK) ( @@ -4735,44 +4735,44 @@ BEGIN @queries_top, @work_start_utc, @work_end_utc; - + IF @troubleshoot_performance = 1 BEGIN SET STATISTICS XML OFF; - + EXEC sys.sp_executesql @troubleshoot_update, N'@current_table nvarchar(100)', @current_table; - + EXEC sys.sp_executesql @troubleshoot_info, N'@sql nvarchar(max), @current_table nvarchar(100)', @sql, @current_table; - END; + END; END; /* 'total waits' is special. It's a sum, not a max, so - we cover it above rather than here. + we cover it above rather than here. */ IF @sort_order_is_a_wait = 1 AND @sort_order <> 'total waits' BEGIN SELECT @current_table = 'inserting #plan_ids_with_total_waits', @sql = @isolation_level; - + IF @troubleshoot_performance = 1 BEGIN EXEC sys.sp_executesql @troubleshoot_insert, N'@current_table nvarchar(100)', @current_table; - + SET STATISTICS XML ON; END; - + SELECT @sql += N' SELECT TOP (@top) @@ -4782,7 +4782,7 @@ BEGIN FROM ' + @database_name_quoted + N'.sys.query_store_runtime_stats AS qsrs JOIN ' + @database_name_quoted + N'.sys.query_store_wait_stats AS qsws ON qsrs.plan_id = qsws.plan_id - WHERE 1 = 1 + WHERE 1 = 1 AND qsws.wait_category = ' + CASE @sort_order WHEN 'cpu waits' THEN N'1' @@ -4814,7 +4814,7 @@ BEGIN PRINT LEN(@sql); PRINT @sql; END; - + INSERT #plan_ids_with_total_waits WITH(TABLOCK) ( @@ -4835,23 +4835,23 @@ BEGIN @queries_top, @work_start_utc, @work_end_utc; - + IF @troubleshoot_performance = 1 BEGIN SET STATISTICS XML OFF; - + EXEC sys.sp_executesql @troubleshoot_update, N'@current_table nvarchar(100)', @current_table; - + EXEC sys.sp_executesql @troubleshoot_info, N'@sql nvarchar(max), @current_table nvarchar(100)', @sql, @current_table; - END; + END; END; /*End populating sort-helping tables*/ @@ -5093,7 +5093,7 @@ CROSS APPLY JOIN #plan_ids_with_total_waits AS waits ON qsrs.plan_id = waits.plan_id AND waits.database_id = @database_id' - END; + END; SELECT @sql += N' @@ -6689,9 +6689,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.first_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -6703,9 +6703,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.last_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -6931,9 +6931,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.first_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -6945,9 +6945,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.last_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -7172,9 +7172,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.first_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -7186,9 +7186,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.last_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -7390,9 +7390,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.first_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.first_execution_time AT TIME ZONE @timezone @@ -7404,9 +7404,9 @@ FROM WHEN @timezone IS NULL THEN SWITCHOFFSET - ( + ( qsrs.last_execution_time, - @utc_offset_string + @utc_offset_string ) WHEN @timezone IS NOT NULL THEN qsrs.last_execution_time AT TIME ZONE @timezone @@ -7809,11 +7809,11 @@ BEGIN CASE WHEN @timezone IS NULL THEN - SWITCHOFFSET - ( - qspf.create_time, - @utc_offset_string - ) + SWITCHOFFSET + ( + qspf.create_time, + @utc_offset_string + ) WHEN @timezone IS NOT NULL THEN qspf.create_time AT TIME ZONE @timezone END, @@ -7823,11 +7823,11 @@ BEGIN CASE WHEN @timezone IS NULL THEN - SWITCHOFFSET - ( - qspf.last_updated_time, - @utc_offset_string - ) + SWITCHOFFSET + ( + qspf.last_updated_time, + @utc_offset_string + ) WHEN @timezone IS NOT NULL THEN qspf.last_updated_time AT TIME ZONE @timezone END,