Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Documentation/sp_Blitz_Checks_by_Priority.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Before adding a new check, make sure to add a Github issue for it first, and hav

If you want to change anything about a check - the priority, finding, URL, or ID - open a Github issue first. The relevant scripts have to be updated too.

CURRENT HIGH CHECKID: 266.
If you want to add a new one, start at 267.
CURRENT HIGH CHECKID: 267.
If you want to add a new one, start at 268.

| Priority | FindingsGroup | Finding | URL | CheckID |
|----------|-----------------------------|---------------------------------------------------------|------------------------------------------------------------------------|----------|
Expand Down Expand Up @@ -276,6 +276,7 @@ If you want to add a new one, start at 267.
| 210 | Non-Default Database Scoped Config | Legacy CE | https://www.BrentOzar.com/go/dbscope | 195 |
| 210 | Non-Default Database Scoped Config | Parameter Sniffing | https://www.BrentOzar.com/go/dbscope | 196 |
| 210 | Non-Default Database Scoped Config | Query Optimizer Hotfixes | https://www.BrentOzar.com/go/dbscope | 197 |
| 210 | Non-Default Database Scoped Config | All Others | https://www.BrentOzar.com/go/dbscope | 267 |
| 230 | Security | Control Server Permissions | https://www.BrentOzar.com/go/sa | 104 |
| 230 | Security | Database Owner <> SA | https://www.BrentOzar.com/go/owndb | 55 |
| 230 | Security | Database Owner is Unknown | | 213 |
Expand Down
84 changes: 38 additions & 46 deletions sp_Blitz.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7749,52 +7749,44 @@ IF @ProductVersionMajor >= 10
IF @Debug IN (1, 2) RAISERROR('Running CheckId [%d] through [%d] and [%d] through [%d].', 0, 1, 194, 197, 237, 255) WITH NOWAIT;

INSERT INTO #DatabaseScopedConfigurationDefaults (configuration_id, [name], default_value, default_value_for_secondary, CheckID)
SELECT 1, 'MAXDOP', '0', NULL, 194
UNION ALL
SELECT 2, 'LEGACY_CARDINALITY_ESTIMATION', '0', NULL, 195
UNION ALL
SELECT 3, 'PARAMETER_SNIFFING', '1', NULL, 196
UNION ALL
SELECT 4, 'QUERY_OPTIMIZER_HOTFIXES', '0', NULL, 197
UNION ALL
SELECT 6, 'IDENTITY_CACHE', '1', NULL, 237
UNION ALL
SELECT 7, 'INTERLEAVED_EXECUTION_TVF', '1', NULL, 238
UNION ALL
SELECT 8, 'BATCH_MODE_MEMORY_GRANT_FEEDBACK', '1', NULL, 239
UNION ALL
SELECT 9, 'BATCH_MODE_ADAPTIVE_JOINS', '1', NULL, 240
UNION ALL
SELECT 10, 'TSQL_SCALAR_UDF_INLINING', '1', NULL, 241
UNION ALL
SELECT 11, 'ELEVATE_ONLINE', 'OFF', NULL, 242
UNION ALL
SELECT 12, 'ELEVATE_RESUMABLE', 'OFF', NULL, 243
UNION ALL
SELECT 13, 'OPTIMIZE_FOR_AD_HOC_WORKLOADS', '0', NULL, 244
UNION ALL
SELECT 14, 'XTP_PROCEDURE_EXECUTION_STATISTICS', '0', NULL, 245
UNION ALL
SELECT 15, 'XTP_QUERY_EXECUTION_STATISTICS', '0', NULL, 246
UNION ALL
SELECT 16, 'ROW_MODE_MEMORY_GRANT_FEEDBACK', '1', NULL, 247
UNION ALL
SELECT 17, 'ISOLATE_SECURITY_POLICY_CARDINALITY', '0', NULL, 248
UNION ALL
SELECT 18, 'BATCH_MODE_ON_ROWSTORE', '1', NULL, 249
UNION ALL
SELECT 19, 'DEFERRED_COMPILATION_TV', '1', NULL, 250
UNION ALL
SELECT 20, 'ACCELERATED_PLAN_FORCING', '1', NULL, 251
UNION ALL
SELECT 21, 'GLOBAL_TEMPORARY_TABLE_AUTO_DROP', '1', NULL, 252
UNION ALL
SELECT 22, 'LIGHTWEIGHT_QUERY_PROFILING', '1', NULL, 253
UNION ALL
SELECT 23, 'VERBOSE_TRUNCATION_WARNINGS', '1', NULL, 254
UNION ALL
SELECT 24, 'LAST_QUERY_PLAN_STATS', '0', NULL, 255;
EXEC dbo.sp_MSforeachdb 'USE [?]; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; INSERT INTO #BlitzResults (CheckID, DatabaseName, Priority, FindingsGroup, Finding, URL, Details)
VALUES
(1, 'MAXDOP', '0', NULL, 194),
(2, 'LEGACY_CARDINALITY_ESTIMATION', '0', NULL, 195),
(3, 'PARAMETER_SNIFFING', '1', NULL, 196),
(4, 'QUERY_OPTIMIZER_HOTFIXES', '0', NULL, 197),
(6, 'IDENTITY_CACHE', '1', NULL, 237),
(7, 'INTERLEAVED_EXECUTION_TVF', '1', NULL, 238),
(8, 'BATCH_MODE_MEMORY_GRANT_FEEDBACK', '1', NULL, 239),
(9, 'BATCH_MODE_ADAPTIVE_JOINS', '1', NULL, 240),
(10, 'TSQL_SCALAR_UDF_INLINING', '1', NULL, 241),
(11, 'ELEVATE_ONLINE', 'OFF', NULL, 242),
(12, 'ELEVATE_RESUMABLE', 'OFF', NULL, 243),
(13, 'OPTIMIZE_FOR_AD_HOC_WORKLOADS', '0', NULL, 244),
(14, 'XTP_PROCEDURE_EXECUTION_STATISTICS', '0', NULL, 245),
(15, 'XTP_QUERY_EXECUTION_STATISTICS', '0', NULL, 246),
(16, 'ROW_MODE_MEMORY_GRANT_FEEDBACK', '1', NULL, 247),
(17, 'ISOLATE_SECURITY_POLICY_CARDINALITY', '0', NULL, 248),
(18, 'BATCH_MODE_ON_ROWSTORE', '1', NULL, 249),
(19, 'DEFERRED_COMPILATION_TV', '1', NULL, 250),
(20, 'ACCELERATED_PLAN_FORCING', '1', NULL, 251),
(21, 'GLOBAL_TEMPORARY_TABLE_AUTO_DROP', '1', NULL, 252),
(22, 'LIGHTWEIGHT_QUERY_PROFILING', '1', NULL, 253),
(23, 'VERBOSE_TRUNCATION_WARNINGS', '1', NULL, 254),
(24, 'LAST_QUERY_PLAN_STATS', '0', NULL, 255),
(25, 'PAUSED_RESUMABLE_INDEX_ABORT_DURATION_MINUTES', '1440', NULL, 267),
(26, 'DW_COMPATIBILITY_LEVEL', '0', NULL, 267),
(27, 'EXEC_QUERY_STATS_FOR_SCALAR_FUNCTIONS', '1', NULL, 267),
(28, 'PARAMETER_SENSITIVE_PLAN_OPTIMIZATION', '1', NULL, 267),
(29, 'ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITY', '0', NULL, 267),
(31, 'CE_FEEDBACK', '1', NULL, 267),
(33, 'MEMORY_GRANT_FEEDBACK_PERSISTENCE', '1', NULL, 267),
(34, 'MEMORY_GRANT_FEEDBACK_PERCENTILE_GRANT', '1', NULL, 267),
(35, 'OPTIMIZED_PLAN_FORCING', '1', NULL, 267),
(37, 'DOP_FEEDBACK', '0', NULL, 267),
(38, 'LEDGER_DIGEST_STORAGE_ENDPOINT', 'OFF', NULL, 267),
(39, 'FORCE_SHOWPLAN_RUNTIME_PARAMETER_COLLECTION', '0', NULL, 267);

EXEC dbo.sp_MSforeachdb 'USE [?]; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; INSERT INTO #BlitzResults (CheckID, DatabaseName, Priority, FindingsGroup, Finding, URL, Details)
SELECT def1.CheckID, DB_NAME(), 210, ''Non-Default Database Scoped Config'', dsc.[name], ''https://www.brentozar.com/go/dbscope'', (''Set value: '' + COALESCE(CAST(dsc.value AS NVARCHAR(100)),''Empty'') + '' Default: '' + COALESCE(CAST(def1.default_value AS NVARCHAR(100)),''Empty'') + '' Set value for secondary: '' + COALESCE(CAST(dsc.value_for_secondary AS NVARCHAR(100)),''Empty'') + '' Default value for secondary: '' + COALESCE(CAST(def1.default_value_for_secondary AS NVARCHAR(100)),''Empty''))
FROM [?].sys.database_scoped_configurations dsc
INNER JOIN #DatabaseScopedConfigurationDefaults def1 ON dsc.configuration_id = def1.configuration_id
Expand Down
62 changes: 41 additions & 21 deletions sp_BlitzIndex.sql
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ DECLARE @ColumnList NVARCHAR(MAX);
DECLARE @ColumnListWithApostrophes NVARCHAR(MAX);
DECLARE @PartitionCount INT;
DECLARE @OptimizeForSequentialKey BIT = 0;
DECLARE @ResumableIndexesDisappearAfter INT = 0;
DECLARE @StringToExecute NVARCHAR(MAX);

/* If user was lazy and just used @ObjectName with a fully qualified table name, then lets parse out the various parts */
Expand Down Expand Up @@ -2612,7 +2613,17 @@ OPTION (RECOMPILE);';
[object_id], index_id, name, sql_text, last_max_dop_used, partition_number, state, state_desc,
start_time, last_pause_time, total_execution_time, percent_complete, page_count )
EXEC sp_executesql @dsql, @params = N'@i_DatabaseName NVARCHAR(128)', @i_DatabaseName = @DatabaseName;
END TRY

SET @dsql=N'SELECT @ResumableIndexesDisappearAfter = CAST(value AS INT)
FROM ' + QUOTENAME(@DatabaseName) + N'.sys.database_scoped_configurations
WHERE name = ''PAUSED_RESUMABLE_INDEX_ABORT_DURATION_MINUTES''
AND value > 0;'
EXEC sp_executesql @dsql, N'@ResumableIndexesDisappearAfter INT OUT', @ResumableIndexesDisappearAfter out;

IF @ResumableIndexesDisappearAfter IS NULL
SET @ResumableIndexesDisappearAfter = 0;

END TRY
BEGIN CATCH
RAISERROR (N'Skipping #IndexResumableOperations population due to error, typically low permissions', 0,1) WITH NOWAIT;
END CATCH
Expand Down Expand Up @@ -3294,29 +3305,34 @@ BEGIN
SELECT
N'Resumable Index Operation' AS finding,
N'This may invalidate your analysis!' AS warning,
iro.state_desc + ' on ' + iro.db_schema_table_index +
iro.state_desc + N' on ' + iro.db_schema_table_index +
CASE iro.state
WHEN 0 THEN
' at MAXDOP ' + CONVERT(NVARCHAR(30), iro.last_max_dop_used) +
'. First started ' + CONVERT(NVARCHAR(50), iro.start_time, 120) + '. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + '% complete after ' +
N' at MAXDOP ' + CONVERT(NVARCHAR(30), iro.last_max_dop_used) +
N'. First started ' + CONVERT(NVARCHAR(50), iro.start_time, 120) + N'. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + N'% complete after ' +
CONVERT(NVARCHAR(30), iro.total_execution_time) +
' minute(s). This blocks DDL and can pile up ghosts.'
N' minute(s). ' +
CASE WHEN @ResumableIndexesDisappearAfter > 0
THEN N' Will be automatically removed by the database server at ' + CONVERT(NVARCHAR(50), (DATEADD(mi, @ResumableIndexesDisappearAfter, iro.last_pause_time)), 121) + N'. '
ELSE N' Will not be automatically removed by the database server. '
END
+ N'This blocks DDL and can pile up ghosts.'
WHEN 1 THEN
' since ' + CONVERT(NVARCHAR(50), iro.last_pause_time, 120) + '. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + '% complete' +
N' since ' + CONVERT(NVARCHAR(50), iro.last_pause_time, 120) + N'. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + N'% complete' +
/*
At 100% completion, resumable indexes open up a transaction and go back to paused for what ought to be a moment.
Updating statistics is one of the things that it can do in this false paused state.
Updating stats can take a while, so we point it out as a likely delay.
It seems that any of the normal operations that happen at the very end of an index build can cause this.
*/
CASE WHEN iro.percent_complete > 99.9
THEN '. It is probably still running, perhaps updating statistics.'
ELSE ' after ' + CONVERT(NVARCHAR(30), iro.total_execution_time)
+ ' minute(s). This blocks DDL, fails transactions needing table-level X locks, and can pile up ghosts.'
THEN N'. It is probably still running, perhaps updating statistics.'
ELSE N' after ' + CONVERT(NVARCHAR(30), iro.total_execution_time)
+ N' minute(s). This blocks DDL, fails transactions needing table-level X locks, and can pile up ghosts.'
END
ELSE ' which is an undocumented resumable index state description.'
ELSE N' which is an undocumented resumable index state description.'
END AS details,
N'https://www.BrentOzar.com/go/resumable' AS URL,
iro.more_info AS [More Info]
Expand Down Expand Up @@ -3738,25 +3754,29 @@ BEGIN
N'Resumable Index Operation Paused' AS finding,
iro.[database_name] AS [Database Name],
N'https://www.BrentOzar.com/go/resumable' AS URL,
iro.state_desc + ' on ' + iro.db_schema_table_index +
' since ' + CONVERT(NVARCHAR(50), iro.last_pause_time, 120) + '. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + '% complete' +
iro.state_desc + N' on ' + iro.db_schema_table_index +
N' since ' + CONVERT(NVARCHAR(50), iro.last_pause_time, 120) + N'. ' +
CONVERT(NVARCHAR(6), CONVERT(MONEY, iro.percent_complete)) + N'% complete' +
/*
At 100% completion, resumable indexes open up a transaction and go back to paused for what ought to be a moment.
Updating statistics is one of the things that it can do in this false paused state.
Updating stats can take a while, so we point it out as a likely delay.
It seems that any of the normal operations that happen at the very end of an index build can cause this.
*/
CASE WHEN iro.percent_complete > 99.9
THEN '. It is probably still running, perhaps updating statistics.'
ELSE ' after ' + CONVERT(NVARCHAR(30), iro.total_execution_time)
+ ' minute(s). This blocks DDL, fails transactions needing table-level X locks, and can pile up ghosts.'
THEN N'. It is probably still running, perhaps updating statistics.'
ELSE N' after ' + CONVERT(NVARCHAR(30), iro.total_execution_time)
+ N' minute(s). This blocks DDL, fails transactions needing table-level X locks, and can pile up ghosts. '
END +
CASE WHEN @ResumableIndexesDisappearAfter > 0
THEN N' Will be automatically removed by the database server at ' + CONVERT(NVARCHAR(50), (DATEADD(mi, @ResumableIndexesDisappearAfter, iro.last_pause_time)), 121) + N'. '
ELSE N' Will not be automatically removed by the database server. '
END AS details,
'Old index: ' + ISNULL(i.index_definition, 'not found. Either the index is new or you need @IncludeInactiveIndexes = 1') AS index_definition,
N'Old index: ' + ISNULL(i.index_definition, N'not found. Either the index is new or you need @IncludeInactiveIndexes = 1') AS index_definition,
i.secret_columns,
i.index_usage_summary,
'New index: ' + iro.reserved_MB_pretty_print + '; Old index: ' + ISNULL(sz.index_size_summary,'not found.') AS index_size_summary,
'New index: ' + iro.sql_text AS create_tsql,
N'New index: ' + iro.reserved_MB_pretty_print + N'; Old index: ' + ISNULL(sz.index_size_summary,'not found.') AS index_size_summary,
N'New index: ' + iro.sql_text AS create_tsql,
iro.more_info
FROM #IndexResumableOperations iro
LEFT JOIN #IndexSanity AS i ON i.database_id = iro.database_id
Expand Down
Loading