From 96d82ac1f48e7858d8d94e9f00710559a9799705 Mon Sep 17 00:00:00 2001 From: Aleksei Guzev Date: Thu, 7 Jul 2022 22:22:10 +0300 Subject: [PATCH] Update SQL Assessment API release notes --- .../sql-assessment-api/DefaultRuleset.csv | 77 +- .../sql-assessment-api/release-notes.md | 80 + .../manage/sql-assessment-api/ruleset.json | 1612 ++++++++++++++--- 3 files changed, 1445 insertions(+), 324 deletions(-) diff --git a/samples/manage/sql-assessment-api/DefaultRuleset.csv b/samples/manage/sql-assessment-api/DefaultRuleset.csv index 7e903161..8e6d5a8b 100644 --- a/samples/manage/sql-assessment-api/DefaultRuleset.csv +++ b/samples/manage/sql-assessment-api/DefaultRuleset.csv @@ -22,7 +22,7 @@ "TF1236","override","TRUE","Low","TF 1236 is not needed in SQL Server 2012 SP3, SQL Server 2014 SP1 and higher","Disable trace flag 1236 in SQL Server 2012 SP3, SQL Server 2014 SP1 and higher versions","","Trace Flag 1236 enables database-level lock partitioning. Starting with SQL Server 2012 SP3 and SQL Server 2014 SP1, this behavior is controlled by the engine and trace flag 1236 has no effect.",,,,,,"[11.0.6020,12.0) [12.0.4100,)",,, "TF1462","definition","TRUE","Medium","TF 1462 should be disabled to allow Log Stream Compression","Disable trace flag 1462 to allow log stream compression","DefaultRuleset, TraceFlag, Performance, AvailabilityGroups","Trace Flag 1462 disables log stream compression for asynchronous availability groups. This feature is enabled by default on asynchronous replicas to optimize network bandwidth.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/tune-compression-for-availability-group","Server","Windows Linux",,"SqlServer","[11.0,)",,, "TF2312","definition","TRUE","Low","TF 2312 sets the default cardinality estimation model","Trace Flag 2312 does not apply to this SQL Server version. Check if you need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, QueryOptimizer, Performance","Trace Flag 2312 sets the Query Optimizer cardinality estimation model to the default version of the database compability level of SQL Server 2014 and higher versions. If the database compatibility level is lower than 120, enabling trace flag 2312 uses the cardinality estimation model of SQL Server 2014 (120).","https://support.microsoft.com/help/2801413","Server","Windows",,"SqlServer","[11.0,)",,, -"TF2312","override","False","Information",,"TF2312 sets the query optimizer cardinality estimation model to SQL Server 2014 or above versions, dependent of the compatibility level of the database","DefaultRuleset, TraceFlag, QueryOptimizer, Performance",,,,,,,"[12.0, )",,, +"TF2312","override","False","Information",,"TF2312 sets the query optimizer cardinality estimation model to SQL Server 2014 or above versions, dependent of the compatibility level of the database","",,,,,,,"[12.0, )",,, "TF2330","definition","TRUE","Low","TF 2330 disables recording of index usage stats","Check if you need to disable recording of index usage stats by setting non-default trace flag 2330","DefaultRuleset, TraceFlag, Performance, Indexes","Trace Flag 2330 disables recording of index usage stats, which could lead to a non-yielding condition in SQL 2005.","https://blogs.msdn.microsoft.com/ialonso/2012/10/08/faq-around-sys-dm_db_index_usage_stats","Server","Windows Linux",,"SqlServer","[11.0,)",,, "TF2340","definition","TRUE","Information","TF 2340 disables Batch Sorts for optimized nested loops joins","Trace Flag 2340 disables Batch Sorts for optimized nested loops joins","DefaultRuleset, TraceFlag, QueryOptimizer, Performance","Trace Flag 2340 causes SQL Server not to use a sort operation (batch sort) for optimized nested loops joins when generating a plan. Verify need to set a non-default trace flag with the current system build and configuration.","https://docs.microsoft.com/sql/t-sql/database-console-commands/dbcc-traceon-trace-flags-transact-sql","Server","Windows Linux",,"SqlServer","[11.0,)",,, "TF2371","definition","TRUE","Information","TF 2371 enables a linear recompilation threshold for statistics","Enable trace Flag 2371 to allow linear recompilation threshold for statistics","DefaultRuleset, TraceFlag, Performance, Statistics","Trace Flag 2371 causes SQL Server to change the fixed update statistics threshold to a linear update statistics threshold. This is especially useful to keep statistics updated on large tables.","https://docs.microsoft.com/sql/relational-databases/statistics/statistics#auto_update_statistics-option","Server","Windows",,"SqlServer","[11.0,)",,, @@ -44,9 +44,9 @@ "TF4138","definition","TRUE","Low","TF 4138 causes plans to not use Row Goal adjustments","Trace flag 4138 does not apply to this SQL Server version. Verify need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, QueryOptimizer, Performance","Trace Flag 4138 causes SQL Server to generate a plan that does not use row goal adjustments with queries that contain TOP, OPTION (FAST N), IN, or EXISTS keywords. Starting with SQL Server 2016 SP1, to accomplish this at the query level use the USE HINT 'DISABLE_OPTIMIZER_ROWGOAL' query hint. However it does not apply to this SQL Server version. Verify need to set a Non-default trace flag with current system build and configuration.","https://support.microsoft.com/help/2667211","Server","Windows Linux",,"SqlServer","[11.0,)",,, "TF4139","override","TRUE","Information",,"Trace Flag 4139 enables automatic statistics for any key ordering. Verify need to set a non-default trace flag with the current system build and configuration","","Trace Flag 4139 enables automatically generated quick statistics (histogram amendment) regardless of key column status. This trace flag is recommended to be set in cases where queries access newly inserted key values that may change plan shape, but the new values are not yet updated in the statistics histogram for the affected columns. In this case, regardless of the leading statistics column status (ascending, descending, or stationary), the histogram used to estimate cardinality will be adjusted at query compile time. This trace flag does not apply to the cardinality estimation model of SQL Server 2012 and earlier versions (CE 70). Verify need to set a non-default trace flag with the current system build and configuration.",,,,,,"[11.0.3431,11.0.5058) [11.0.5532,)",,, "TF4139","definition","TRUE","Low","TF 4139 enables automatic statistics for any key ordering","Trace flag 4139 does not apply to this SQL Server version. Verify need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, Statistics","Trace Flag 4139 enables automatically generated quick statistics (histogram amendment) regardless of key column status. However, this trace flag does not apply to this SQL Server version. Verify need to set a non-default trace flag with the current system build and configuration.","https://support.microsoft.com/help/2952101","Server","Windows Linux",,"SqlServer","[11.0,)",,, -"TF4199","definition","TRUE","Information","TF 4199 enables query optimizer fixes","Trace Flag 4199 enables Query Optimizer fixes. Verify need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, QueryOptimizer","Trace Flag 4199 enables Query Optimizer fixes released in SQL Server Cumulative Updates and Service Packs.","http://support.microsoft.com/help/974006","Server","Windows Linux",,"SqlServer","[11.0, 14.0)",,, +"TF4199","definition","TRUE","Information","TF 4199 enables query optimizer fixes","Trace Flag 4199 enables Query Optimizer fixes. Verify need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, QueryOptimizer","Trace Flag 4199 enables Query Optimizer fixes released in SQL Server Cumulative Updates and Service Packs.","http://support.microsoft.com/help/974006","Server","Windows",,"SqlServer","[11.0, 14.0)",,, "TF6498","definition","TRUE","Low","TF 6498 enables additional concurrent large queries","Trace Flag 6498 does not apply to this SQL Server version. Verify need to set a non-default trace flag with the current system build and configuration","DefaultRuleset, TraceFlag, Performance, Memory","Trace Flag 6498 enables more than one large query compilation to gain access to the big gateway when there is sufficient memory available. However, this trace flag does not apply to this SQL Server version. This trace flag can be used to keep memory usage for the compilation of incoming queries under control, avoiding compilation waits for concurrent large queries. Starting with SQL Server 2014 SP2 and SQL Server 2016, this behavior is controlled by the engine and trace flag 1236 has no effect.","https://support.microsoft.com/help/3024815","Server","Windows Linux",,"SqlServer","[12.0.5000,)",,, -"TF6532","definition","TRUE","Information","TF 6532 enables performance improvements for spatial data","Enable trace flag 6532 to enable performance improvements for spatial data","DefaultRuleset, TraceFlag, Performance","Trace Flag 6532 enables performance improvements of query operations with spatial data types. The performance gain will vary, depending on the configuration, the types of queries, and the objects.","https://support.microsoft.com/help/3107399","Server","Windows Linux",,"SqlServer","[11.0.6020,11.0.6518)",,, +"TF6532","definition","TRUE","Information","TF 6532 enables performance improvements for spatial data","Enable trace flag 6532 to enable performance improvements for spatial data","DefaultRuleset, TraceFlag, Performance","Trace Flag 6532 enables performance improvements of query operations with spatial data types. The performance gain will vary, depending on the configuration, the types of queries, and the objects.","https://support.microsoft.com/help/3107399","Server","Windows",,"SqlServer","[11.0.6020,11.0.6518)",,, "TF6532.6533","override","TRUE","Low",,"Disable trace flag 6532 in SQL Server 2016 and higher versions.","",,,,,,,"[13.0,)",,, "TF6532.6533","definition","TRUE","Information","TF 6532 and 6533 improve spatial data performance","Enable trace flags 6532 and 6533 to improve spatial data performance","DefaultRuleset, TraceFlag, Performance","Trace flags 6532 and 6533 enable performance improvements of query operations with spatial data types. The performance gain will vary, depending on the configuration, types of queries, and objects.","https://support.microsoft.com/help/3107399","Server","Windows",,"SqlServer","[11.0,)",,, "TF6534","override","TRUE","Information",,"Enable trace flag 6534 to enable performance improvement of query operations with spatial data types","","Trace Flag 6534 enables performance improvements of query operations with spatial data types. The performance gain will vary, depending on the configuration, the types of queries, and the objects.",,,,,,"[11.0.6020,12.0) [12.0.5000,13.0)",,, @@ -68,9 +68,10 @@ "HypotheticalIndexes","definition","TRUE","Medium","Hypothetical indexes found","Drop hypothetical @{IndexName} index for @{Schema}.@{Object}","DefaultRuleset, Indexes, Performance","Database has indexes that are marked as hypothetical. Hypothetical indexes are created by the Database Tuning Assistant (DTA) during its tests. If a DTA session was interrupted, these indexes may not be deleted. It is recommended to drop these objects as soon as possible.","https://blogs.technet.microsoft.com/anurag_sharma/2008/04/15/hypothetical-indexes","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "HypotheticalStatistics","definition","TRUE","Medium","Hypothetical statistics found","Drop hypothetical @{StatName} statistics for @{Schema}.@{Object}","DefaultRuleset, Statistics","Database has statistics that are marked as hypothetical. Hypothetical statistics are created by the Database Tuning Assistant (DTA) during its tests. If a DTA session was interrupted, these statistics may not be deleted. It is recommended to drop these objects as soon as possible.","https://blogs.technet.microsoft.com/anurag_sharma/2008/04/15/hypothetical-indexes","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "LatestCU","definition","TRUE","Medium","SQL Server version is not supported","Update SQL Server and install service packs and cumulative updates. Current product version @{ProductVersion} of SQL Server is out of support","DefaultRuleset, Security, UpdateIssues","The Microsoft Support Lifecycle (MSL) policy offers a minimum of 10 years of support (5 years Mainstream support and 5 years Extended support). It also provides support for 1 year after the new service pack was released, older service packs are unsupported.","https://support.microsoft.com/help/321185/how-to-determine-the-version-edition-and-update-level-of-sql-server-an","Server","Windows Linux",,"SqlServer","[11.0,)",,, -"LatestCU","override","TRUE","Low","SQL Server instance is not up to date","Update SQL Server and install service packs and cumulative updates. Current product version @{ProductVersion} is not up to date","","On an installed instance of SQL Server, we recommend that you apply the latest security updates and critical updates including general distribution releases (GDRs), service packs (SPs), and cumulative updates (CUs).",,,,,,"[11.0.7001, 12.0) [12.0.6024, 13.0) [13.0.5026,)",,, -"LatestCU","override","TRUE","Low","SQL Server instance is up to date","Product version @{ProductVersion} is latest available","",,,,,,,"[11.0.7507, 12.0) [12.0.6433, 13.0) [13.0.6300, 14.0) [14.0.3430, 15.0) [15.0.4198,)",,, -"FKNoIndexes","definition","TRUE","Medium","Foreign key constraints should have corresponding indexes","Create a corresponding index for each foreign key. There is no index on foreign keys: @{ConstraintName}","DefaultRuleset, Performance, Indexes","Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index. However, manually creating an index on a foreign key is often useful.","https://docs.microsoft.com/sql/relational-databases/tables/primary-and-foreign-key-constraints","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, +"LatestCU","override","TRUE","Low","SQL Server instance is not up to date","Update SQL Server and install service packs and cumulative updates. Current product version @{ProductVersion} is not up to date","","On an installed instance of SQL Server, we recommend that you apply the latest security updates and critical updates including general distribution releases (GDRs), service packs (SPs), and cumulative updates (CUs).",,,,,,"[11.0.7001, 12.0) [12.0.6024, 13.0) [13.0.6300,)",,, +"LatestCU","override","TRUE","Low","SQL Server instance is up to date","Product version @{ProductVersion} is latest available","",,,,,,,"[11.0.7507, 12.0) [12.0.6439, 13.0) [13.0.6419, 14.0) [14.0.3445, 15.0) [15.0.4236,)",,, +"LatestCU","override","TRUE","Low",,"Upgrade SQL Server 2012 to receive full product updates and Microsoft Support. End of support is July, 12 2022.","","We recommend upgrading to the latest SQL Server version to keep your instances secure and compliant. If upgrade is not an option at this point, follow the help link to protect your SQL Server 2012 with Extended Security Updates (ESU).","https://docs.microsoft.com/sql/sql-server/end-of-support/sql-server-extended-security-updates",,,,,"[11.0, 12.0)",,, +"FKNoIndexes","definition","TRUE","Medium","Foreign key constraints should have corresponding indexes","Create a corresponding index on each foreign key in tables: @{TableName}","DefaultRuleset, Performance, Indexes","Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index. However, manually creating an index on a foreign key is often useful.","https://docs.microsoft.com/sql/relational-databases/tables/primary-and-foreign-key-constraints","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "MissedIndexes","definition","TRUE","Information","Potentially missing indexes","Create index on @{Table} with key columns @{KeyCols}@{IncludedCols: and included columns: #}","DefaultRuleset, Performance, Indexes","Potentially missing indexes were found based on query history. It may be important to revise them.","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "FullBackup","definition","TRUE","Medium","Full backup is missed or outdated","Create full backup. Last full backup is over @{threshold} days old","DefaultRuleset, Backup","Database doesn't have any full backup or the latest full backup is over 7 days old.","https://docs.microsoft.com/sql/relational-databases/backup-restore/create-a-full-database-backup-sql-server","Database","Windows Linux",,"SqlServer","[11.0,)","NOT: model tempdb","7", "OutdatedTranLogBackup","definition","TRUE","Medium","Transaction Log backup is missed or outdated","Create transaction log backup. Database recovery model: @{recovery_model_desc}","DefaultRuleset, Backup","Database does not have any transaction Log backup since the latest full or differential backup, or it's older than @{threshold}H.","https://docs.microsoft.com/sql/relational-databases/backup-restore/back-up-a-transaction-log-sql-server","Database","Windows Linux",,"SqlServer","[11.0,)","NOT: master model msdb tempdb","24", @@ -88,7 +89,7 @@ "TempDBFilesNotLess8","definition","TRUE","Medium","Number of TempDB data files should be at least 8","Add extra data files to TempDB. There are @{physical_name} data files, should be at least 8","DefaultRuleset, TempDB, Performance, DBFileConfiguration","Number of TempDB data files should correlate with the number of (logical) processors on the machine. As a general rule, if the number of logical processors is less than or equal to 8, use the same number of data files as logical processors. If the number of logical processors is greater than 8, use 8 data files and then if contention continues, increase the number of data files by multiples of 4 until the contention is reduced to acceptable levels or make changes to the workload/code.","https://support.microsoft.com/kb/2154845","Server","Windows Linux",,"SqlServer","[11.0,)",,, "TempDBFilesAutoGrowth","definition","TRUE","Medium","TempDB data files have different auto-growth settings","Make auto-growth settings the same for each TempDB data file","DefaultRuleset, TempDB, Performance, DBFileConfiguration","TempDB data files should be of equal size within each filegroup, as SQL Server uses a proportional-fill algorithm that favors allocations in files with more free space.","https://docs.microsoft.com/sql/relational-databases/databases/tempdb-database","Server","Windows Linux",,"SqlServer","[11.0,)",,, "FilesAutogrowth","definition","TRUE","Medium","Database files auto-growth over 1GB","Set file growth to less than 1GB for files: @{FileName}","DefaultRuleset, Performance, DBFileConfiguration","A data or log file will be extended with auto-growth value to prevent the lack of free space in files. This process can perform significant impact on SQL Server performance if auto-growth value gets over 1 GB. By default, SQL Server will put zeros to a newly allocated space. And the more space it takes, the more time it takes to initialize it.","https://support.microsoft.com/help/315512/considerations-for-the-autogrow-and-autoshrink-settings-in-sql-server","Database","Windows Linux",,"SqlServer, ManagedInstance","[13.0.4001,)",,, -"DuplicateIndexes","definition","TRUE","Low","Duplicate indexes","Remove duplicate indexes in table @{Table}: @{ToDelete}","DefaultRuleset, Performance, Indexes","A SQL Server index is an on-disk or in-memory structure associated with a table or view that speeds retrieval of rows from the table or view. An index contains keys built from one or more columns in the table or view. ","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, +"DuplicateIndexes","definition","TRUE","Low","Duplicate indexes","Remove duplicate indexes in table @{Table}: @{Indexes}","DefaultRuleset, Performance, Indexes","A SQL Server index is an on-disk or in-memory structure associated with a table or view that speeds retrieval of rows from the table or view. An index contains keys built from one or more columns in the table or view. ","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "RedundantIndexes","definition","TRUE","Low","Tables with redundant indexes","Remove redundant indexes in table @{Table}: @{Indexes}","DefaultRuleset, Performance, Indexes","There are tables with possibly redundant indexes according to the set of key and included columns. We recommended to revise all these objects as soon as possible.","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "UserObjectsInMaster","definition","TRUE","Low","User objects in master database","Remove user objects from 'master' database: @{Object_Name}","DefaultRuleset, masterDB, Backup","We highly recommend you not create user objects in the master database. If it's unavoidable for some reason, make sure to back up the database more frequently.","https://docs.microsoft.com/sql/relational-databases/databases/master-database","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","master",, "HighCPUUsage","definition","TRUE","Medium","High CPU usage on server","Investigate high CPU utilization on server hosting this instance. Last 2 hours: total CPU usage is ~@{AVGTotalCPUUsage}%, usage by SQL Server is ~@{AVGSQLCPUUsage}%","DefaultRuleset, Performance, CPU","Keeping CPU usage rates within normal ranges is vital for servers hosting SQL Server instances. A continually high rate of CPU usage may indicate the need to upgrade the CPU or add multiple processors. Alternatively, a high CPU usage rate may indicate a poorly tuned or designed application. Optimizing the application can lower CPU utilization.","https://docs.microsoft.com/sql/relational-databases/performance-monitor/monitor-cpu-usage","Server","Windows",,"SqlServer, ManagedInstance","[11.0,)",,"70", @@ -104,16 +105,16 @@ "AgentAlertsSeverity24","definition","TRUE","Low","Agent doesn't rise alerts for errors with severity 24","Create alerts for errors: @{error_ids}","DefaultRuleset, Agent","Events are generated by SQL Server and entered into the Microsoft Windows application log. SQL Server Agent reads the application log and compares events written there to alerts that you have defined. When SQL Server Agent finds a match, it fires an alert, which is an automated response to an event. In addition to monitoring SQL Server events, SQL Server Agent can also monitor performance conditions and Windows Management Instrumentation (WMI) events.","https://docs.microsoft.com/sql/ssms/agent/alerts","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "WeakPassword","definition","TRUE","Medium","SQL logins have weak passwords","Set strong passwords for logins: @{PasswordData}","DefaultRuleset, Security, WeakPassword","Some SQL logins have weak passwords. Make sure that you use a strong password for each of your SQL logins to decrease vulnerabilities.","https://docs.microsoft.com/sql/relational-databases/security/strong-passwords","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "VLFCount","definition","TRUE","Medium","VLF count","Update transaction log settings to reduce number of VLFs. Current number is: @{RecoveryUnitId}","DefaultRuleset, Backup, Performance","The SQL Server Database Engine divides each physical log file internally into a number of virtual log files (VLFs). Virtual log files have no fixed size, and there is no fixed number of virtual log files for a physical log file. The Database Engine chooses the size of the virtual log files dynamically while it is creating or extending log files. The Database Engine tries to maintain a small number of virtual files. The size of the virtual files after a log file has been extended is the sum of the size of the existing log and the size of the new file increment. The size or number of virtual log files cannot be configured or set by administrators. If the log files grow to a large size in many small increments, they will have many virtual log files. This can slow down database startup and also log backup and restore operations. Conversely, if the log files are set to a large size with few or just one increment, they will have few very large virtual log files. We recommend that you assign log files a size value close to the final size required, using the required increments to achieve optimal VLF distribution, and also have a relatively large growth_increment value.","https://docs.microsoft.com/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,"50", -"TF8015","definition","TRUE","Medium","TF 8015 disables auto-detection and NUMA setup","Disable trace flag 8015 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, CPU, NUMA","SQL Server allows you to group CPUs into nodes referred to as soft-NUMA. You usually configure soft-NUMA when you have many CPUs and do not have hardware NUMA, but you can also use soft-NUMA to subdivide hardware NUMA nodes into smaller groups.","https://techcommunity.microsoft.com/t5/SQL-Server-Support/How-It-Works-Soft-NUMA-I-O-Completion-Thread-Lazy-Writer-Workers/ba-p/316044","Server","Windows Linux",,"SqlServer","[11.0,11.0.3349)",,, +"TF8015","definition","TRUE","Medium","TF 8015 disables auto-detection and NUMA setup","Disable trace flag 8015 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, CPU, NUMA","SQL Server allows you to group CPUs into nodes referred to as soft-NUMA. You usually configure soft-NUMA when you have many CPUs and do not have hardware NUMA, but you can also use soft-NUMA to subdivide hardware NUMA nodes into smaller groups.","https://techcommunity.microsoft.com/t5/SQL-Server-Support/How-It-Works-Soft-NUMA-I-O-Completion-Thread-Lazy-Writer-Workers/ba-p/316044","Server","Windows",,"SqlServer","[11.0,11.0.3349)",,, "TF8032","definition","TRUE","Medium","TF 8032 reverts cache limit parameters to SQL Server 2005 RTM","Disable trace flag 8032","DefaultRuleset, TraceFlag, Performance","Trace Flag 8032 reverts the cache limit parameters to the SQL Server 2005 RTM setting but can cause poor performance if large caches make less memory available for other memory consumers like BP.",,"Server","Windows Linux",,"SqlServer","[11.0,)",,, -"TF8744","definition","TRUE","Medium","TF 8744 disables pre-fetching for Nested Loop operator","Disable trace flag 8744","DefaultRuleset, TraceFlag, Performance","Trace flag 8744 disables pre-fetching for the Nested Loops operator. Incorrect use of this trace flag may cause additional physical reads when SQL Server executes plans that contain the Nested Loops operator.","https://support.microsoft.com/help/920093/tuning-options-for-sql-server-when-running-in-high-performance-workloa","Server","Windows Linux",,"SqlServer","[11.0,12.0)",,, -"TF9347","definition","TRUE","Medium","TF 9347 disables batch mode for sort operator","Disable trace flag 9347 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance","Trace flag 9347 disables batch mode for sort operator. SQL Server 2016 (13.x) introduced a new batch mode sort operator that boosts performance for many analytical queries.",,"Server","Windows Linux",,"SqlServer","[11.0,13.0)",,, -"TF9349","definition","TRUE","Medium","TF 9349 disables batch mode for top N sort operator","Disable trace flag 9349 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance","Trace flag 9349 disables batch mode for top N sort operator. SQL Server 2016 (13.x) introduced a new batch mode top sort operator that boosts performance for many analytical queries.",,"Server","Windows Linux",,"SqlServer","[11.0,13.0)",,, -"TF9389","definition","TRUE","Medium","TF 9389 enables dynamic memory grant for batch mode operators","Disable trace flag 9389 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance, TempDB","Trace flag 9389 enables additional dynamic memory grant for batch mode operators. If a query does not get all the memory it needs, it spills data to TempDB, incurring additional I/O and potentially impacting query performance. If the dynamic memory grant trace flag is enabled, a batch mode operator may ask for additional memory and avoid spilling to TempDB if additional memory is available.",,"Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,13.0)",,, -"TF9476","definition","TRUE","Medium","TF 9476 causes SQL Server to generate plan using Simple Containment assumption","Disable trace flag 9476 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance, QueryOptimizer","Trace flag 9476 causes SQL Server to generate a plan using the Simple Containment assumption instead of the default Base Containment assumption, under the query optimizer cardinality estimation model of SQL Server 2014 (12.x) through SQL Server 2017 versions.",,"Server","Windows Linux",,"SqlServer","[11.0,13.0)",,, -"TF9481","definition","TRUE","Medium","TF 9481 enables Legacy CE model","Disable trace flag 9481 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, QueryOptimizer, Performance","Trace flag 9481 enables you to set the query optimizer cardinality estimation model to the SQL Server 2012 (11.x) and earlier versions, irrespective of the compatibility level of the database.",,"Server","Windows Linux",,"SqlServer","[11.0,12.0)",,, +"TF8744","definition","TRUE","Medium","TF 8744 disables pre-fetching for Nested Loop operator","Disable trace flag 8744","DefaultRuleset, TraceFlag, Performance","Trace flag 8744 disables pre-fetching for the Nested Loops operator. Incorrect use of this trace flag may cause additional physical reads when SQL Server executes plans that contain the Nested Loops operator.","https://support.microsoft.com/help/920093/tuning-options-for-sql-server-when-running-in-high-performance-workloa","Server","Windows",,"SqlServer","[11.0,12.0)",,, +"TF9347","definition","TRUE","Medium","TF 9347 disables batch mode for sort operator","Disable trace flag 9347 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance","Trace flag 9347 disables batch mode for sort operator. SQL Server 2016 (13.x) introduced a new batch mode sort operator that boosts performance for many analytical queries.",,"Server","Windows",,"SqlServer","[11.0,13.0)",,, +"TF9349","definition","TRUE","Medium","TF 9349 disables batch mode for top N sort operator","Disable trace flag 9349 for this SQL Server instance. This trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance","Trace flag 9349 disables batch mode for top N sort operator. SQL Server 2016 (13.x) introduced a new batch mode top sort operator that boosts performance for many analytical queries.",,"Server","Windows",,"SqlServer","[11.0,13.0)",,, +"TF9389","definition","TRUE","Medium","TF 9389 enables dynamic memory grant for batch mode operators","Disable trace flag 9389 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance, TempDB","Trace flag 9389 enables additional dynamic memory grant for batch mode operators. If a query does not get all the memory it needs, it spills data to TempDB, incurring additional I/O and potentially impacting query performance. If the dynamic memory grant trace flag is enabled, a batch mode operator may ask for additional memory and avoid spilling to TempDB if additional memory is available.",,"Server","Windows",,"SqlServer, ManagedInstance","[11.0,13.0)",,, +"TF9476","definition","TRUE","Medium","TF 9476 causes SQL Server to generate plan using Simple Containment assumption","Disable trace flag 9476 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance, QueryOptimizer","Trace flag 9476 causes SQL Server to generate a plan using the Simple Containment assumption instead of the default Base Containment assumption, under the query optimizer cardinality estimation model of SQL Server 2014 (12.x) through SQL Server 2017 versions.",,"Server","Windows",,"SqlServer","[11.0,13.0)",,, +"TF9481","definition","TRUE","Medium","TF 9481 enables Legacy CE model","Disable trace flag 9481 for this SQL Server instance. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, QueryOptimizer, Performance","Trace flag 9481 enables you to set the query optimizer cardinality estimation model to the SQL Server 2012 (11.x) and earlier versions, irrespective of the compatibility level of the database.",,"Server","Windows",,"SqlServer","[11.0,12.0)",,, "TF10204","definition","TRUE","Medium","TF 10204 disables merge/recompress","Disable trace flag 10204. The trace flag does not apply to this SQL Server version","DefaultRuleset, TraceFlag, Performance, ColumnStore","Trace flag 10204 disables merge/recompress during columnstore index reorganization. In SQL Server 2016 (13.x), when a columnstore index is reorganized, there is new functionality to automatically merge any small compressed rowgroups into larger compressed rowgroups, as well as recompressing any rowgroups that have a large number of deleted rows.",,"Server","Windows Linux",,"SqlServer","[11.0,13.0)",,, -"SPNaming","definition","TRUE","Medium","Stored procedure naming","Rename the following stored procedures to eliminate 'sp_' prefix: @{ObjectName}","DefaultRuleset, Naming","In SQL Server, the sp_ prefix designates system stored procedures. If you use that prefix for your stored procedures, the name of your procedure might conflict with the name of a system stored procedure that will be created in the future. If such a conflict occurs, your application might break if your application refers to the procedure without qualifying the reference by schema. In this situation, the name will bind to the system procedure instead of to your procedure.","https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172115(v=vs.100)","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"SPNaming","definition","TRUE","Low","Stored procedure naming","Rename the following stored procedures to eliminate 'sp_' prefix: @{ObjectName}","DefaultRuleset, Naming","In SQL Server, the sp_ prefix designates system stored procedures. If you use that prefix for your stored procedures, the name of your procedure might conflict with the name of a system stored procedure that will be created in the future. If such a conflict occurs, your application might break if your application refers to the procedure without qualifying the reference by schema. In this situation, the name will bind to the system procedure instead of to your procedure.","https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172115(v=vs.100)","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "ObjectNamingSpecialChar","definition","TRUE","Low","Special characters in object names","Rename the following objects to eliminate special characters: @{ObjectName}","DefaultRuleset, Naming","If you name a database object by using any character in the following table, you make it more difficult not only to reference that object but also to read code that contains the name of that object.","https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172134(v=vs.100)","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "ColumnNamingSpecialChar","definition","TRUE","Low","Special characters in column names","Remove whitespaces, left and right square brackets, single and double quotation marks from column names: @{ObjectName}","DefaultRuleset, Naming","Using whitespaces, left and right square brackets, single and double quotation marks in database object names makes it more difficult not only to reference that object, but also to read code that contains the name of that object.","https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172134(v=vs.100)","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FnNaming","definition","TRUE","Medium","User function naming","Rename the following functions to eliminate 'fn_ prefix': @{ObjectName}","DefaultRuleset, Naming","In SQL Server, the fn_ prefix designates system functions. If you use that prefix for your functions, the name of your function might conflict with the name of a system function that will be created in the future. If such a conflict occurs, your application might break if your application refers to the function without qualifying the reference by schema. In this situation, the name will bind to the system function instead of to your function.","https://docs.microsoft.com/sql/t-sql/statements/create-function-transact-sql","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, @@ -124,7 +125,7 @@ "NUMANodeSingleCPU","definition","TRUE","Medium","Single CPU assigned to NUMA node","Assign additional CPUs to NUMA nodes with only one CPU","DefaultRuleset, NUMA, CPU, Memory, Performance","Microsoft SQL Server is non-uniform memory access (NUMA) aware. NUMA architecture provides a scalable solution to performance problem. Computers with hardware NUMA have more than one system bus, each serving a small set of processors. Each group of processors has its own memory and possibly its own I/O channels, but each CPU can access memory associated with other groups in a coherent way. Each group is called a NUMA node. The number of CPUs within a NUMA node depends on the hardware vendor. Your hardware manufacturer can tell you if your computer supports hardware NUMA.","https://docs.microsoft.com/previous-versions/sql/sql-server-2008-r2/ms178144(v=sql.105)","Server","Windows",,"SqlServer, ManagedInstance","[11.0,)",,, "NUMANodeNoCPU","definition","TRUE","Medium","NUMA nodes without CPUs","Assign CPUs to each NUMA node","DefaultRuleset, NUMA, Performance, CPU, Memory","Microsoft SQL Server is non-uniform memory access (NUMA) aware. NUMA architecture provides a scalable solution to performance problem. Computers with hardware NUMA have more than one system bus, each serving a small set of processors. Each group of processors has its own memory and possibly its own I/O channels, but each CPU can access memory associated with other groups in a coherent way. Each group is called a NUMA node. The number of CPUs within a NUMA node depends on the hardware vendor. Your hardware manufacturer can tell you if your computer supports hardware NUMA.","https://docs.microsoft.com/previous-versions/sql/sql-server-2008-r2/ms178144(v=sql.105)","Server","Windows",,"SqlServer, ManagedInstance","[11.0,)",,, "IndexKeyGuid","definition","TRUE","Low","Guid in clustered index key column","Remove GUIDs in clustered indexes keys: @{IndexName}","DefaultRuleset, Indexes, Performance","A big reason for a clustered index is when you often want to retrieve rows for a range of values for a given column. Because the data is physically arranged in that order, the rows can be extracted very efficiently. Something like a GUID, while excellent for a primary key, could be positively detrimental to performance, as there will be additional cost for inserts and no perceptible benefit on selects.","https://azure.microsoft.com/blog/uniqueidentifier-and-clustered-indexes/","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master tempdb model msdb",, -"IndexesLargeKeys","definition","TRUE","Low","Indexes keys with more than @{threshold} bytes","Remove keys larger than @{threshold} bytes in @{FullName} index","DefaultRuleset, Indexes, Performance","When you design an index that contains many key columns, or large-size columns, calculate the size of the index key to make sure that you do not exceed the maximum index key size. SQL Server retains the @{threshold}-byte limit for the maximum total size of all index key columns. This excludes nonkey columns that are included in the definition of nonclustered indexes.","http://msdn.microsoft.com/library/ms191241.aspx","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,13.0)","NOT: master model msdb tempdb","900", +"IndexesLargeKeys","definition","TRUE","Low","Indexes keys with more than @{threshold} bytes","Remove keys larger than @{threshold} bytes in @{FullName} index","DefaultRuleset, Indexes, Performance","When you design an index that contains many key columns, or large-size columns, calculate the size of the index key to make sure that you do not exceed the maximum index key size. SQL Server retains the @{threshold}-byte limit for the maximum total size of all index key columns. This excludes nonkey columns that are included in the definition of nonclustered indexes.","http://msdn.microsoft.com/library/ms191241.aspx","Database","Windows",,"SqlServer, ManagedInstance","[11.0,13.0)","NOT: master model msdb tempdb","900", "IndexesLargeKeysNonClust","definition","TRUE","Low","NonClustered indexes keys with more than @{threshold} bytes","Remove keys larger than @{threshold} bytes in @{FullName} index","DefaultRuleset, Indexes, Performance","When you design an index that contains many key columns, or large-size columns, calculate the size of the index key to make sure that you do not exceed the maximum index key size. SQL Server retains the @{threshold}-byte limit for the maximum total size of all non-clustered index key columns. This excludes nonkey columns that are included in the definition of nonclustered indexes.","http://msdn.microsoft.com/library/ms191241.aspx","Database","Windows Linux",,"SqlServer, ManagedInstance","[13.0,)","NOT: master model msdb tempdb","1700", "IndexesLargeKeysClust","definition","TRUE","Low","Clustered indexes keys with more than @{threshold} bytes","Remove keys larger than @{threshold} bytes in @{FullName} index","DefaultRuleset, Indexes, Performance","When you design an index that contains many key columns, or large-size columns, calculate the size of the index key to make sure that you do not exceed the maximum index key size. SQL Server retains the @{threshold}-byte limit for the maximum total size of all clustered index key columns. This excludes nonkey columns that are included in the definition of nonclustered indexes.","http://msdn.microsoft.com/library/ms191241.aspx","Database","Windows Linux",,"SqlServer, ManagedInstance","[13.0,)","NOT: master model msdb tempdb","900", "DisabledIndexes","definition","TRUE","Medium","Disabled indexes exist","Remove or enable disabled index: @{FullName}","DefaultRuleset, Indexes, Performance","If you need to load a lot of data quickly, you can disable nonclustered indexes in order to improve performance. After the data load finishes, enable the nonclustered indexes again by rebuilding them. This technique works best in large data warehouse environments where entire dimension tables might be reloaded from scratch every night. Disabling nonclustered indexes is safer than dropping and recreating them because scripting indexes is hard. Unfortunately, sometimes our load processes crash before enabling the indexes again, or sometimes we manually load data and we forget to rebuild them.","https://docs.microsoft.com/sql/relational-databases/indexes/disable-indexes-and-constraints","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, @@ -135,15 +136,13 @@ "TableNoIndex","definition","TRUE","Low","Tables without indexes","Review @{TableName} table and create reasonable indexes","DefaultRuleset, Indexes, Performance","Each table in the database has one or more pages. To keep track of those pages, SQL Server uses a special set of pages, called IAM (for Index Allocation Map) pages. In spite of the word “Index” in the name, IAMs are used for non-indexed tables as well. These are called heaps. All the data is there, but the only way to find anything is to read it starting at the beginning. For a very large table, this will be terribly inefficient.","https://docs.microsoft.com/sql/relational-databases/indexes/heaps-tables-without-clustered-indexes","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master tempdb model msdb",, "TableNoClusteredIndex","definition","TRUE","Low","Tables without clustered indexes","Review @{TableName} table and create clustered index","DefaultRuleset, Indexes, Performance","Tables without clustered indexes are called heaps. They’re scattered on disk anywhere that SQL Server can find a spot, and they’re not stored in any order whatsoever. This can make for really fast inserts – SQL Server can just throw the data down – but slow selects, updates, and deletes.","https://docs.microsoft.com/sql/relational-databases/indexes/heaps-tables-without-clustered-indexes","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master tempdb model msdb",, "TablePSAlign","definition","TRUE","Low","Table index not aligned with PS","Re-create @{IndexName} index in @{TableName} table to have it aligned with current schema","DefaultRuleset, Indexes, Performance","Table partitioning is a complex way to break out your large tables into smaller, more manageable chunks, but it comes with a lot of management heartache. One of the challenges is making sure that your indexes are partitioned and aligned the same way as your clustered index.","https://docs.microsoft.com/sql/relational-databases/partitions/partitioned-tables-and-indexes","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master tempdb model msdb",, -"LoginNoPassword","definition","False","Low","SQL logins have no passwords","Set strong passwords for logins: @{PasswordData}","DefaultRuleset, Security, WeakPassword","Password complexity policies are designed to deter brute force attacks by increasing the number of possible passwords. Make sure that you use a strong password for each of your SQL logins to decrease vulnerabilities.","https://docs.microsoft.com/sql/relational-databases/security/password-policy","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"LoginEqPassword","definition","False","Low","Passwords and SQL login names are the same","Review logins that have passwords equal to SQL login names: @{PasswordData}","DefaultRuleset, Security, WeakPassword","Password complexity policies are designed to deter brute force attacks by increasing the number of possible passwords. Make sure that you use passwords that are different from your SQL login names.","https://docs.microsoft.com/sql/relational-databases/security/password-policy","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "SystemHealth","definition","TRUE","High","System Health important messages","Error @{Error_Number} occured @{Error_Count} times. Last time was @{Last_Logged_Days_Ago} days ago","DefaultRuleset, XEvent, SystemHealth, Performance","The system_health session is an Extended Events session that is included by default with SQL Server. This session starts automatically when the SQL Server Database Engine starts, and runs without any noticeable performance effects. The session collects system data that you can use to help troubleshoot performance issues in the Database Engine","https://docs.microsoft.com/sql/relational-databases/extended-events/use-the-system-health-session","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "RarelyUsedIndex","definition","TRUE","Low","Rarely used index","Revise rarely used index @{IndexName}","DefaultRuleset, Indexes, Performance","Rarely used indexes can slow down database's performance. Time of write operations is increased because of index maintenance, but index is not used quite often. It makes sense to compare impact of writing operations versus rare reading speedup.","https://docs.microsoft.com/sql/t-sql/statements/drop-index-transact-sql","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "UnusedIndex","definition","TRUE","Medium","Unused index","Revise unused @{IndexName} index on @{TableName} table","DefaultRuleset, Index, Performance","Unused indexes can slow down database's performance. Time of write operations is increased because of index maintenance, but index is not used anywhere.","https://docs.microsoft.com/sql/t-sql/statements/drop-index-transact-sql","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "SkewedCompatibilityLevel","definition","TRUE","Low","Database with skewed compatibility level","Update database compatibility level. Current level is @{CompatibilityLevel}","DefaultRuleset, CompatibilityLevel, Security, Performance, UpdateIssues","Some databases may have a compatibility level lower than the allowed level by the Database Engine.","https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-compatibility-level","Database","Windows Linux",,,"[11.0,)",,, "PendingDiskIORequests","definition","TRUE","Medium","Pending disk I/O requests","Solve I/O related issues to get rid of pending requests","DefaultRuleset, IO, Performance","A database management system (DBMS), such as SQL Server, relies on the timeliness of file input and output (I/O) operations. The proper configuration and maintenance of the I/O subsystem is critical to a successful SQL Server deployment.","https://support.microsoft.com/en-sg/help/897284/diagnostics-in-sql-server-help-detect-stalled-and-stuck-i-o-operations","Server","Windows Linux",,,"[11.0,)",,, "MaxDOP","definition","TRUE","Medium","MaxDOP should be less or equal to number of CPUs","Update MaxDOP configuration option value: @{max_dop}. It shouldn't exceed @{online_logical_processors} - number of processors used by SQL Server","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[11.0,)",,, -"MaxDOPFewNUMA","definition","TRUE","Low","MAXDOP set in accordance with CPU count","Update MAXDOP configuration option value: @{max_dop}. It should not exceed the number of logical processors per NUMA node","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[11.0, 13.0)",,, +"MaxDOPFewNUMA","definition","TRUE","Low","MAXDOP set in accordance with CPU count","Update MAXDOP configuration option value: @{max_dop}. It should not exceed the number of logical processors per NUMA node","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows",,"SqlServer","[11.0, 13.0)",,, "DbIntegrity","definition","TRUE","Medium","Database Integrity Checks","Run 'DBCC CHECKDB' command checks","DefaultRuleset, DBCC, Performance, DataIntegrity","The DBCC CHECKDB command checks the integrity of the objects in a database and should be run on a regular basis. This statement is used to perform different operations in your database and can be broken down into four categories: Maintenance, Miscellaneous, Informational, and Validation.","https://msdn.microsoft.com/library/ms176064.aspx","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: tempdb","7", "DirectCatalogUpdates","definition","TRUE","Low","Direct Catalog Updates","Avoid using direct catalog update feature","DefaultRuleset, DBCC, Deprecated","The 'allow updates' option is still present in the sp_configure stored procedure, although its functionality is unavailable in SQL Server. The setting has no effect. Starting with SQL Server 2005, direct updates to the system tables are not supported.","https://docs.microsoft.com/sql/database-engine/configure-windows/allow-updates-server-configuration-option","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: tempdb",, "DataPurityCheck","definition","TRUE","Low","Data Purity Check","Enable data purity validation with 'DBCC CHECKDB ([DatabaseName]) WITH DATA_PURITY' command","DefaultRuleset, DBCC, DataIntegrity","The DBCC CHECKDB command checks the integrity of the objects in a database and should be run on a regular basis. One thing that this command does not check in databases created in versions prior to SQL Server 2005 is the integrity of the data in the columns until it has been run once with the DATA_PURITY option. Adding the DATA_PURITY option causes the CHECKDB command to look for column values that are invalid or out of range. Any database that was created in SQL Server 2005 or later will include the DATA_PURITY check by default; but if the database is being upgraded from an earlier version, you must run the command with the DATA_PURITY option at least once using the following command and then fix any data issues.","http://support.microsoft.com/kb/923247","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, @@ -154,12 +153,12 @@ "XTPTooManyBuckets","definition","TRUE","Low","Too many buckets","Make number of buckets of @{IndexFullName} index equal to distinct rows. It has @{total_bucket_count} buckets and there are @{DistinctCnt} in table, which wastes memory and marginally slows down full table scans","DefaultRuleset, Index, Performance, XTP","Memory-optimized HASH indexes behave different from NONCLUSTERED indexes. They are optimized for point-lookup operations, and do not support ordered scans or inequality seek operations. You must specify a value for the BUCKET_COUNT parameter when you create the memory-optimized table.","https://techcommunity.microsoft.com/t5/sql-server/in-memory-oltp-indexes-part-2-performance-troubleshooting-guide/ba-p/385725","Database","Windows Linux",,"SqlServer, ManagedInstance","[12.0,)","NOT: master model msdb tempdb",, "XTPTooFewBuckets","definition","TRUE","Medium","Too few buckets","Make number of buckets of @{IndexFullName} index equal to distinct rows. It has @{total_bucket_count} buckets and there are @{DistinctCnt} in table, which leads to chaining records","DefaultRuleset, Index, Performance, XTP","Memory-optimized HASH indexes behave different from NONCLUSTERED indexes. They are optimized for point-lookup operations, and do not support ordered scans or inequality seek operations. You must specify a value for the BUCKET_COUNT parameter when you create the memory-optimized table.","https://techcommunity.microsoft.com/t5/sql-server/in-memory-oltp-indexes-part-2-performance-troubleshooting-guide/ba-p/385725","Database","Windows Linux",,"SqlServer, ManagedInstance","[12.0,)","NOT: master model msdb tempdb",, "XTPRangeIXHealth","definition","TRUE","Low","NonClustered index retry amount","Review @{IndexFullName} index as its retry count is over @{RetryCountPct}% of total, which indicates possible concurrency issues","DefaultRuleset, Index, Performance, XTP","When a database with a memory-optimized table is restarted, the index is built by inserting one row at a time into memory. The count of page splits, merges, and consolidation can help you understand the work done to build the index when a database is brought online. Large numbers of retries are indicative of concurrency issues.","https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-xtp-nonclustered-index-stats-transact-sql","Database","Windows Linux",,"SqlServer, ManagedInstance","[12.0,)","NOT: master model msdb tempdb",, -"TF6533Misuse","definition","TRUE","Low","'STRelate' and 'STAsBinary' functions unexpected results due to TF 6533","Disable trace flag 6533 to avoid unexpected results of 'STRelate' and 'STAsBinary' functions","DefaultRuleset, TraceFlag, Performance, TF6533","The STRelate and STAsBinary functions may return unexpected results when trace flag 6533 is enabled. Do not use this trace flag if your workload involves either of these functions.","https://support.microsoft.com/help/3107399","Database","Windows Linux",,"SqlServer","[11.0.6020, 11.0.6518)","NOT: master model msdb tempdb",, +"TF6533Misuse","definition","TRUE","Low","'STRelate' and 'STAsBinary' functions unexpected results due to TF 6533","Disable trace flag 6533 to avoid unexpected results of 'STRelate' and 'STAsBinary' functions","DefaultRuleset, TraceFlag, Performance, TF6533","The STRelate and STAsBinary functions may return unexpected results when trace flag 6533 is enabled. Do not use this trace flag if your workload involves either of these functions.","https://support.microsoft.com/help/3107399","Database","Windows",,"SqlServer","[11.0.6020, 11.0.6518)","NOT: master model msdb tempdb",, "UntrustedConstraints","definition","TRUE","Low","Untrusted constraints","Execute 'ALTER TABLE WITH CHECK CHECK CONSTRAINT ' statement to avoid possible performance issues: @{constraint_name} constraints are not trusted for referential integrity","DefaultRuleset, Performance, DataIntegrity","If you need to load a lot of data quickly, you can disable keys and constraints in order to improve performance. After the data load finishes, enable them again, and SQL Server will check them behind the scenes. This technique works best in large data warehouse environments where entire dimension tables might be reloaded from scratch every night. Disabling constraints is usually safer and easier than dropping and recreating them.","https://docs.microsoft.com/sql/t-sql/statements/alter-table-transact-sql","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "PercentAutogrows","definition","TRUE","Low","Database files have growth ratio in percentage","Do not use ""File Growth In Percent"" for Autogrowth setting. Affected files: @{fileName} have growth ratio set in percentage","DefaultRuleset, Performance, DBFileConfiguration, DBConfiguration","Some database files have a growth ratio set in percentage. Over time, this could lead to uncontrolled disk space allocation and extended time to perform these growths","https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-file-and-filegroup-options","Database","Windows Linux",,"SqlServer","[11.0,)","NOT: master model msdb tempdb",, "StatsUpdate","definition","TRUE","Low","Statistics need to be updated","Update stats in @{TableName} table to improve query performance","DefaultRuleset, Performance, Statistics, QueryOptimizer","The Query Optimizer determines whether an index is useful for a specific query by evaluating the stored statistics. If the statistics become out of date and significant changes have occurred against the underlying data, this can result in less than optimal query performance. In most cases, it's best to let SQL Server maintain the statistics. If you turn 'Auto Create Stats' and 'Auto Update Stats' off, then it is up to you to keep the statistics up-to-date somehow. Failure to do so will lead to poor query performance. Most applications should have these options ON. When the Auto Update Statistics setting is ON, the Query Optimizer updates statistics when they are used by a query and when they might be out-of-date. Statistics become out-of-date after insert, update, delete, or merge operations change the data distribution in the table or indexed view. The Query Optimizer determines when statistics might be out-of-date by counting the number of data modifications since the last statistics update and comparing the number of modifications to a threshold. The threshold is based on the number of rows in the table or indexed view. The Query Optimizer checks for out-of-date statistics before compiling a query and before executing a cached query plan. Before compiling a query, the Query Optimizer uses the columns, tables, and indexed views in the query predicate to determine which statistics might be out-of-date. Before executing a cached query plan, the Database Engine verifies that the query plan references up-to-date statistics. The AUTO_UPDATE_STATISTICS option applies to statistics created for indexes, single-columns in query predicates, and statistics that are created by using the CREATE STATISTICS statement. This option also applies to filtered statistics.","https://docs.microsoft.com/sql/relational-databases/statistics/statistics#UpdateStatistics","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,"500", "AdHocQueriesOff","definition","TRUE","Low","Option 'ad hoc distributed queries' should be disabled","Disable 'ad hoc distributed queries' option","DefaultRuleset, Configuration, Security","Ad Hoc Distributed Queries use the OPENROWSET and OPENDATASOURCE functions to connect to remote data sources that use OLE DB. OPENROWSET and OPENDATASOURCE should be used only to reference OLE DB data sources that are accessed infrequently. For any data sources that will be accessed more than several times, define a linked server. Enabling the use of ad hoc names means that any authenticated login to SQL Server can access the provider. SQL Server administrators should enable this feature for providers that are safe to be accessed by any local login.","https://docs.microsoft.com/sql/database-engine/configure-windows/ad-hoc-distributed-queries-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, -"AffinityMasksOverlap","definition","TRUE","Low","Affinity Mask and Affinity I/O Mask overlapping","Correct Affinity Mask and Affinity IO Mask overlap. AffinityMask = @{affinity_mask}, Affinity64Mask = @{affinity64_mask}, AffinityIOMask = @{affinity_io_mask}, Affinity64IOMask = @{affinity64_io_mask}","DefaultRuleset, Configuration, Performance","Enabling a CPU with both the affinity mask and the affinity I/O mask can slow performance by forcing the processor to be overused. When specified either the affinity mask or the affinity I/O mask options they must both be specified, but only enables each CPU no more than once. The same CPU should not be enabled in both the affinity mask option and the affinity I/O mask option. The bits that correspond to each CPU should be in one of the following states.","https://docs.microsoft.com/sql/relational-databases/policy-based-management/correct-affinity-mask-and-affinity-input-and-output-mask-overlap","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AffinityMasksOverlap","definition","TRUE","Low","Affinity Mask and Affinity I/O Mask overlapping","Correct Affinity Mask and Affinity IO Mask overlap","DefaultRuleset, Configuration, Performance","Enabling a CPU with both the affinity mask and the affinity I/O mask can slow performance by forcing the processor to be overused. When specified either the affinity mask or the affinity I/O mask options they must both be specified, but only enables each CPU no more than once. The same CPU should not be enabled in both the affinity mask option and the affinity I/O mask option. The bits that correspond to each CPU should be in one of the following states.","https://docs.microsoft.com/sql/relational-databases/policy-based-management/correct-affinity-mask-and-affinity-input-and-output-mask-overlap","Server","Windows Linux",,"SqlServer","[11.0,)",,, "AgentSvcAccNotRecommended","definition","TRUE","Low","'SQL Server Agent' service uses non-recommended account","Use another account to run 'SQL Server Agent' service. Current account '@{attr::service::SQLAgent.account}' is not recommended","DefaultRuleset, Configuration","Running the 'SQL Server Agent' service under 'NT AUTHORITY\SYSTEM' or 'NT AUTHORITY\NETWORKSERVICE' accounts is not recommended for security reasons.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-windows-service-accounts-and-permissions","Server","Windows",,"SqlServer","[11.0,)",,, "AgentSvcAccNotRecommended","override","False","Low",,,"",,,,,,"Express",,,, "AgentSvcAccNotSupported","definition","TRUE","Low","'SQL Server Agent' service uses not supported account","Use another account to run 'SQL Server Agent' service. Current account '@{attr::service::SQLAgent.account}' is not supported","DefaultRuleset, Configuration","Running the 'SQL Server Agent' service under 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\SYSTEM' or 'NT AUTHORITY\NETWORKSERVICE' accounts is not supported.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-windows-service-accounts-and-permissions","Server","Windows",,"SqlServer","[11.0,)",,, @@ -193,11 +192,11 @@ "MaxDOP1NUMA","definition","TRUE","Low","MAXDOP set in accordance with CPU count","Update MAXDOP option according to guideline (see help link). Current MAXDOP value is @{max_dop}, CPU count is @{online_logical_processors}","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[11.0,)",,, "MaxDopFewNumaLess16","definition","TRUE","Low","MAXDOP set in accordance with CPU count","Update MAXDOP configuration option value: @{max_dop}. It should not exceed the number of logical processors per NUMA node","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[13.0,)",,, "MaxDopFewNumaOver16","definition","TRUE","Low","MAXDOP set in accordance to CPU count","Update MAXDOP configuration option value: @{max_dop}. It should be half the number of logical processors per NUMA node with maximum value of 16","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[13.0,)",,, -"MaxDopFewNumaOver8","definition","TRUE","Medium","MAXDOP set in accordance with CPU count","Update MAXDOP configuration option value: @{max_dop}. It should be equal to 8","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows Linux",,"SqlServer","[11.0, 13.0)",,, -"MaxMemory","definition","TRUE","Low","Max allowed memory ","Set 'max server memory' value to @{recommended:N0} MB or less to avoid detrimental memory pressure. Current 'max server memory' value is @{max_server_memory:N0}, which is greater than recommended","DefaultRuleset, Memory, Performance, MaxMemory","Setting the 'max server memory' value too high can cause a single instance of SQL Server to compete for memory with other SQL Server instances hosted on the same machine. However, setting this value too low could cause significant memory pressure and performance problems.","https://docs.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,,"2147483647" +"MaxDopFewNumaOver8","definition","TRUE","Medium","MAXDOP set in accordance with CPU count","Update MAXDOP configuration option value: @{max_dop}. It should be equal to 8","DefaultRuleset, MaxDOP, Performance, Configuration, NUMA, CPU","The Microsoft SQL Server max degree of parallelism (MAXDOP) configuration option controls the number of processors that are used for the execution of a query in a parallel plan. This option determines the number of threads that are used for the query plan operators that perform the work in parallel. Depending on whether SQL Server is set up on a symmetric multiprocessing (SMP) computer, a non-uniform memory access (NUMA) computer, or hyperthreading-enabled processors, the max degree of parallelism option should be configured appropriately.","https://support.microsoft.com/kb/2806535","Server","Windows",,"SqlServer","[11.0, 13.0)",,, +"MaxMemory","definition","TRUE","Low","Max allowed memory ","Set 'max server memory' value to @{recommended:N0} MB or less to avoid detrimental memory pressure. Current 'max server memory' value is @{max_server_memory:N0}, which is greater than recommended","DefaultRuleset, Memory, Performance, MaxMemory","Setting the 'max server memory' value too high can cause a single instance of SQL Server to compete for memory with other SQL Server instances hosted on the same machine. However, setting this value too low could cause significant memory pressure and performance problems.","https://docs.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options","Server","Windows Linux",,"SqlServer","[11.0,)",,,"2147483647" "MaxMemory","override","TRUE","Low",,,"",,,,,,"Express",,,,"1410" "MaxMemory","override","TRUE","Low",,,"",,,,,,"Standard",,,,"131072" -"MaxMemorySystem","definition","TRUE","Low","Max server memory exceeds system memory","Set 'max server memory' to @{recommended:N0} MB or less to avoid detrimental memory pressure. System memory of @{sysmem:N0} MB is not sufficient for current 'max server memory' setting of @{max_server_memory:N0} MB","DefaultRuleset, Memory, Performance, MaxMemory","Setting the 'max server memory' value higher than system memory can cause SQL Server to compete for memory with the operating system and processes running on the same machine.","https://docs.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,,"2147483647" +"MaxMemorySystem","definition","TRUE","Low","Max server memory exceeds system memory","Set 'max server memory' to @{recommended:N0} MB or less to avoid detrimental memory pressure. System memory of @{sysmem:N0} MB is not sufficient for current 'max server memory' setting of @{max_server_memory:N0} MB","DefaultRuleset, Memory, Performance, MaxMemory","Setting the 'max server memory' value higher than system memory can cause SQL Server to compete for memory with the operating system and processes running on the same machine.","https://docs.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options","Server","Windows Linux",,"SqlServer","[11.0,)",,,"2147483647" "MaxMemorySystem","override","TRUE","Low",,,"",,,,,,"Express",,,,"1410" "MaxMemorySystem","override","TRUE","Low",,,"",,,,,,"Standard",,,,"131072" "MinMemoryPerQuery","definition","TRUE","Low","Option 'min memory per query' set to default","Set 'min memory per query' option to @{recommended_min_memory_per_query} KB. Current value is '@{min_memory_per_query}'","DefaultRuleset, Configuration, Memory, Performance","The min memory per query option specifies the minimum amount of memory (in kilobytes) that will be allocated for the execution of a query. This is also known as the minimum memory grant. The default value is 1,024 KB. Do not set the min memory per query server configuration option too high, especially on very busy systems, because the query has to wait1 until it can secure the minimum memory requested, or until the value specified in the query wait server configuration option is exceeded. If more memory is available than the specified minimum value required to execute the query, the query is allowed to make use of the additional memory, provided that the memory can be used effectively by the query.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-min-memory-per-query-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, @@ -229,15 +228,27 @@ "WorkerThreadsLargeX64","definition","TRUE","Low","Option 'max worker threads' set to recommended value on x64 system","Reconfigure 'max worker threads' option parameter. Current value (@{max_worker_threads}) is higher than recommended for x64 system (@{recommended_max_worker_threads})","DefaultRuleset, Configuration, Performance, CPU","The max worker threads option configures the number of worker threads that are available to SQL Server processes. The default value for max worker threads is 0. This enables SQL Server to automatically configure the number of worker threads at startup.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-max-worker-threads-server-configuration-option","Server","Windows",,"SqlServer","[11.0,)",,, "WorkerThreadsLargeX86","definition","TRUE","Low","Option 'max worker threads' set to recommended value on x86 system","Reconfigure 'max worker threads' option. Current value (@{max_worker_threads}) is higher than recommended for x86 system (@{recommended_max_worker_threads})","DefaultRuleset, Configuration, Performance, CPU","The max worker threads option configures the number of worker threads that are available to SQL Server processes. The default value for max worker threads is 0. This enables SQL Server to automatically configure the number of worker threads at startup.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-max-worker-threads-server-configuration-option","Server","Windows",,"SqlServer","[11.0,)",,, "XpCmdShellOn","definition","TRUE","Low","Option 'xp_cmdshell' is disabled","Disable 'xp_cmdshell' as it exposes to security risks","DefaultRuleset, Configuration","The xp_cmdshell option is a SQL Server configuration option that enables system administrators to control whether the xp_cmdshell extended stored procedure can be executed on a system. By default, the xp_cmdshell option is disabled on new installations. ","https://docs.microsoft.com/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AccessCheckCache","definition","TRUE","Information","Non-default values for access check cache options","Review non-default values for access check cache options","DefaultRuleset, Configuration","When database objects are accessed by SQL Server, the access check is cached in an internal structure called the access check result cache. The 'access check cache bucket count' and 'access check cache quota' options control the number of hash buckets and number of entries used for access check result cache. The default values of 0 indicate that SQL Server is managing these options.","https://docs.microsoft.com/sql/database-engine/configure-windows/access-check-cache-server-configuration-options","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"AccessCheckCacheRatio","definition","TRUE","Low","Access check cache options ratio","Use a ratio of 1:4 for access check cache options","DefaultRuleset, Configuration","When database objects are accessed by SQL Server, the access check is cached in an internal structure called the access check result cache. The 'access check cache bucket count' and 'access check cache quota' options control the number of hash buckets and number of entries used for access check result cache. These options should be set using a ratio of 1:4.","https://docs.microsoft.com/sql/database-engine/configure-windows/access-check-cache-server-configuration-options","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "Affinity64IOMask","definition","TRUE","Information","Non-default value for 'affinity64 I/O mask' option","Review non-default value @{affinity64_io_mask} for the 'affinity64 I/O mask' option","DefaultRuleset, Performance, Configuration","The 'affinity64 I/O mask' binds SQL Server disk I/O to a specified subset of CPUs, similar to the 'affinity I/O mask' option. Use 'affinity I/O mask' to bind the first 32 processors, and use 'affinity64 I/O mask' to bind the remaining processors.","https://docs.microsoft.com/sql/database-engine/configure-windows/affinity64-input-output-mask-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, "Affinity64Mask","definition","TRUE","Low","Non-default value for 'affinity64 mask' option","Review non-default value @{affinity64_mask} for the 'affinity64 mask' option as it will be removed in a future version","DefaultRuleset, Performance, Configuration","The 'affinity64 mask' binds processors to specific threads, similar to the 'affinity mask' option. Use 'affinity mask' to bind the first 32 processors, and use 'affinity64 mask' to bind the remaining processors.","https://docs.microsoft.com/sql/database-engine/configure-windows/affinity64-mask-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, "AffinityIOMask","definition","TRUE","Information","Non-default value for 'affinity I/O mask' option","Review non-default value @{affinity_io_mask} for the 'affinity I/O mask' option","DefaultRuleset, Performance, Configuration","In a multi-processor system, the 'affinity I/O mask' option binds SQL Server disk I/O to a specified subset of CPUs.","https://docs.microsoft.com/sql/database-engine/configure-windows/affinity-input-output-mask-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, "AffinityMask","definition","TRUE","Low","Non-default value for 'affinity mask' option","Review non-default value @{affinity_mask} for the 'affinity64 mask' option as it will be removed in a future version","DefaultRuleset, Performance, Configuration","In a multi-processor system, the 'affinity mask' option is used to assign certain CPUs to an instance of SQL Server. When the 'affinity mask' is at its default value of 0, the instance of SQL Server can use all processors in the system for its threads. Setting the 'affinity mask' to a non-default value, restricts SQL Server to using only the assigned CPUs.","https://docs.microsoft.com/sql/database-engine/configure-windows/affinity-mask-server-configuration-option","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGDbDisjoined","definition","TRUE","Low","Availability database joined state","Join database '@{databaseName}' to availability group '@{ag_name}' on secondary replica '@{ag_replica_server}'","DefaultRuleset, AlwaysOn","To add a database to an availability group, the database must be an online, read-write database that exists on the server instance that hosts the primary replica. When you add a database, it joins the availability group as a primary database. No corresponding secondary database exists until backups of the new primary database are restored to the server instance that hosts the secondary replica. The new secondary database is in the RESTORING state until it is joined to the availability group. Joining places the secondary database into the ONLINE state and initiates data synchronization with the corresponding primary database.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/join-a-secondary-database-to-an-availability-group-sql-server","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGEndpointEncryption","definition","TRUE","Low","Database mirroring endpoint encryption","Configure data encryption on endpoint '@{endpoint_name}'","","By default, a database mirroring endpoint requires encryption of data sent over mirroring connections. In this case, the endpoint can connect only to endpoints that also use encryption. Unless you can guarantee that your network is secure, we recommend that you require encryption for your database mirroring connections.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/prereqs-restrictions-recommendations-always-on-availability","Server","Windows Linux",,"SqlServer","[11.0,)",,, "AgentXPs","definition","TRUE","Information","Option 'Agent XPs' is disabled","Enable 'Agent XPs' option","DefaultRuleset, Configuration","The 'Agent XPs' option enables the SQL Server Agent extended stored procedures. When this option is disabled, the SQL Server Agent node is not available in SQL Server Management Studio Object Explorer.","https://docs.microsoft.com/sql/database-engine/configure-windows/agent-xps-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"AGFailureConditionLevel","definition","TRUE","Information","Availability group failure-condition level","Review failure-condition level for availability group '@{ag_name}'","DefaultRuleset, AlwaysOn","A flexible failover policy provides granular control over the conditions that cause automatic failover for an availability group. By changing the failure conditions that trigger an automatic failover and the frequency of health checks, you can increase or decrease the likelihood of an automatic failover to support your Service Level Agreement (SLA) for high availability.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/configure-flexible-automatic-failover-policy","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGHealthCheckTimeout","definition","TRUE","Information","Availability group health check timeout","Review non-default value @{health_check_timeout} of health check timeout for availability group '@{ag_name}'. Default value is 30000 milliseconds (30 seconds)","DefaultRuleset, AlwaysOn","The Always On resource DLL monitors the status of internal SQL Server components. sp_server_diagnostics reports the health of these components on an interval controlled by health check timeout. The default settings are optimized for quickly reacting to symptoms of hard failures and limiting downtime, but these settings can also be overly aggressive for certain workloads and configurations.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/availability-group-lease-healthcheck-timeout","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGIsFailoverReady","definition","TRUE","Low","Availability database automatic failover readiness","Database '@{databaseName}' in availability group '@{ag_name}' is not ready for automatic failover. Synchronize database on secondary replica '@{ag_replica_server}'","DefaultRuleset, AlwaysOn","Within the context of an availability group, the primary role and secondary role of availability replicas are typically interchangeable in a process known as failover. During the failover, a qualified secondary replica takes over the primary role, recovers its databases, and brings them online as the new primary databases. An automatic failover causes a qualified secondary replica to automatically transition to the primary role after the primary replica becomes unavailable.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/failover-and-failover-modes-always-on-availability-groups#AutomaticFailover","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGMultipleDHCPListenerSubnets","definition","TRUE","Low","Availability group listener network mode","Reconfigure '@{dns_name}' listener for '@{ag_name}' availability group. Use static IP addresses across multiple subnets","","DHCP network mode is limited to a single subnet that is used for every server instances that hosts a replica in the availability group. To create an availability group across multiple subnets, each subnet requires a static IP address in the listener configuration.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/create-or-configure-an-availability-group-listener-sql-server","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGReplicasDisconnected","definition","TRUE","Low","Availability replica connection state","Resolve connection issue on availability replica '@{ag_replica_server}' in availability group '@{ag_name}'","DefaultRuleset, AlwaysOn","An availability group supports a replicated environment for a discrete set of user databases, known as availability databases. Each set of availability databases is hosted by an availability replica. Two types of availability replicas exist: a single primary replica, which hosts the primary databases, and one to eight secondary replicas, each of which hosts a set of secondary databases and serves as potential failover targets for the availability group. The primary replica sends transaction log records of each primary database to every secondary database. This process - known as data synchronization - occurs at the database level. Every secondary replica caches the transaction log records and then applies them to its corresponding secondary database.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGReplicasSynchronized","definition","TRUE","Low","Availablity replica synchronization health","Resolve synchronization issues on availability replica '@{ag_replica_server}' in availability group '@{ag_name}'","DefaultRuleset, AlwaysOn","An availability group supports a replicated environment for a discrete set of user databases, known as availability databases. Each set of availability databases is hosted by an availability replica. Two types of availability replicas exist: a single primary replica, which hosts the primary databases, and one to eight secondary replicas, each of which hosts a set of secondary databases and serves as potential failover targets for the availability group. The primary replica sends transaction log records of each primary database to every secondary database. This process - known as data synchronization - occurs at the database level. Every secondary replica caches the transaction log records and then applies them to its corresponding secondary database.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server","Server","Windows Linux",,"SqlServer","[11.0,)",,, +"AGTotalNumber","definition","TRUE","Low","Maximum number of Availability Groups","Review the number of Availability Groups (@{ag_id}) currently hosted on the SQL Server instance","DefaultRuleset, AlwaysOn","The actual number of databases and availability groups you can put on a computer (VM or physical) depends on the hardware and workload, but there is no enforced limit. Microsoft has tested up to 10 AGs and 100 DBs per physical machine. Signs of overloaded systems can include, but are not limited to, worker thread exhaustion, slow response times for availability group system views and DMVs, and/or stalled dispatcher system dumps.","https://docs.microsoft.com/sql/database-engine/availability-groups/windows/prereqs-restrictions-recommendations-always-on-availability#PrerequisitesForAGs","Server","Windows Linux",,"SqlServer","[11.0,)",,"10", "AllowUpdates","definition","TRUE","Low","Non-default value for 'allow updates' option","Review non-default value @{allow_updates} for the 'allow updates' option as it has no effect and will be removed in a future version","DefaultRuleset, Performance, Configuration","The 'allow updates' option has no effect and will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.","https://docs.microsoft.com/sql/database-engine/configure-windows/allow-updates-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "AutoStartProcs","definition","TRUE","Low","Automated execution of stored procedures is enabled","Disable automated execution of stored procedures: @{sp_name}","DefaultRuleset, Configuration, Security, Performance","Automated execution of stored procedures during the SQL Server startup may delay the availability of the SQL Server instance during the startup procedure. It also introduces the risk of execution of unauthorized code.","https://docs.microsoft.com/sql/relational-databases/stored-procedures/execute-a-stored-procedure#execute-stored-procedures-automatically","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "AutoUpdateStatsAsync","definition","TRUE","Information","Option 'AUTO_UPDATE_STATISTICS_ASYNC' is enabled","Disable 'AUTO_UPDATE_STATISTICS_ASYNC' option","DefaultRuleset, Configuration","The Query Optimizer could choose a suboptimal query plan if statistics are out-of-date when the query compiles. User database has AUTO_UPDATE_STATISTICS_ASYNC enabled on one or more user databases. ","https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-set-options#auto_update_statistics_async","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "AzDataDiskCache","definition","TRUE","High","Azure disk caching for data files","Set caching to 'ReadOnly' for disk @{name} (@{volume_mount_point}) as it is used for storing data files. Current setting: '@{caching}'","DefaultRuleset, Performance, DBFileConfiguration, DBConfiguration","Uncached IOPS and throughput plus Cached IOPS and throughput will yield the total possible performance available from the virtual machine within the VMs limits.","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-storage#data-file-caching-policies","Database","Windows","AzureVm","SqlServer","[11.0,)","NOT: tempdb",, +"AzDataDiskStriping","definition","TRUE","Information","Azure data disk striping","Consider using data disk striping to increase I/O bandwidth of volume @{volume_mount_point}","DefaultRuleset, Configuration, Performance","There are throughput and bandwidth limits at the data disk level. Applications that consume resources beyond these limits will be throttled. For more throughput and bandwidth, you can add additional data disks and use disk striping. You can use Storage Spaces inside a virtual machine to combine multiple data disks, creating more storage capacity or performance than is available from a single data disk.","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-storage#disk-striping","Server","Windows","AzureVm","SqlServer","[11.0,)",,, "AzDataOnDataDisks","definition","TRUE","Medium","Data files on Azure data disks","Move data files from @{volume_mount_point} to Premium SSD data disk(s)","DefaultRuleset, DBFileConfiguration, DBConfiguration","Azure data disks can be configured for optimal data security and performance. ","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist","Database","Windows","AzureVm","SqlServer","[11.0,)","NOT: tempdb",, "AzDataOnDataDisks","override","TRUE","Low",,,"",,,,,,,,"master model msdb",, "AzDbDefaultLocation","definition","TRUE","Medium","Database default locations","Configure default @{setting_name} file location","DefaultRuleset, Configuration, Performance","Default database file location setting makes new data and transaction log files placed on drives configured for this specific workload.","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist","Server","Windows","AzureVm","SqlServer","[11.0,)",,, @@ -247,29 +258,35 @@ "AzPremSsdDataFiles","override","TRUE","Low",,,"",,,,,,,,"master model msdb",, "AzTempDbFileLocation","definition","TRUE","High","Tempdb files on Azure temp drive","Move tempdb files from @{volume_mount_point} to the local ephemeral SSD (temp disk)","DefaultRuleset, Performance, DBFileConfiguration, DBConfiguration","Storing tempdb files on a local ephemeral SSD improves the performance of workloads that use temporary objects heavily (e.g. queries handling large recordsets, index rebuilds, row versioning isolation levels, temp tables, and triggers).","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist","Database","Windows","AzureVm","SqlServer","[11.0,)","tempdb",, "AzTranLogDiskCache","definition","TRUE","High","Azure disk caching for transaction logs","Set caching to 'None' for disk @{name} (@{volume_mount_point}) as it is used for storing transaction log files. Current setting: '@{caching}'","DefaultRuleset, Performance, DBFileConfiguration, DBConfiguration","There is no performance benefit to enabling caching for the Transaction log disk, and in fact having either Read-only or Read/Write caching enabled on the log drive can decrease the amount of cache available for reads on the data drive","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-storage#data-file-caching-policies","Database","Windows","AzureVm","SqlServer","[11.0,)","NOT: tempdb",, +"BackupCompression","definition","TRUE","Information","Option 'backup compression default' is disabled","Enable 'backup compression default' option","DefaultRuleset, Configuration, Performance, Backup","The 'backup compression default' option determines whether the server instance creates compressed backups by default. Because a compressed backup is smaller than an uncompressed backup of the same data, compressing a backup typically requires less device I/O and therefore usually increases backup speed significantly.","https://docs.microsoft.com/sql/database-engine/configure-windows/view-or-configure-the-backup-compression-default-server-configuration-option","Server","Windows Linux",,"Standard, Enterprise, ManagedInstance","[11.0,)",,, "BackupTables","definition","TRUE","Information","Too many rows in backup or restore history tables","Reduce number of rows in table '@{table_name}' to less than @{threshold}","DefaultRuleset, Configuration","The upgrade process of a SQL Server instance may appear to hang if the number of rows in the following backup and restore system tables is very high: 'backupfile', 'backupmediafamily', 'backupmediaset', 'backupset', 'restorefile', 'restorefilegroup', 'restorehistory'. This is due to the fact that it would take longer to modify the backup and restore system tables in MSDB database.","https://docs.microsoft.com/sql/relational-databases/system-stored-procedures/sp-delete-backuphistory-transact-sql","Server","Windows Linux",,"SqlServer","[11.0,)",,"10000", "C2AuditMode","definition","TRUE","Information","Non-default value for 'c2 audit mode' option","Review non-default value @{c2_audit_mode} for the 'c2 audit mode' option as it will be removed in a future version","DefaultRuleset, Configuration","When enabled, the 'c2 audit mode' option collects all attempts to access statements and objects. Enabling this option triggers a significant amount of data collection over a short period of time for even moderately active Microsoft SQL Server instances.","https://docs.microsoft.com/sql/database-engine/configure-windows/c2-audit-mode-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"CCCompliance","definition","TRUE","Information","Non-default value for 'common criteria compliance enabled' option","Review non-default value @{common_criteria_compliance_enabled} for the 'common criteria compliance enabled' option","DefaultRuleset, Performance, Configuration","SQL Server is being developed to achieve not only the best performance results but also to be the most secure database system ever released. Microsoft has the commitment to be compliant with the most important standards. The most recent SQL Server Editions are getting these recognitions, including the Common Criteria certification. Part of that commitment is the independent third-party evaluation of our products and in using the Common Criteria (CC, ISO15408) as a proven and accepted process to ensure compliance with Common Evaluation Methodologies.","https://docs.microsoft.com/sql/database-engine/configure-windows/common-criteria-compliance-enabled-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"CCCompliance","definition","TRUE","Information","Non-default value for 'common criteria compliance enabled' option","Review non-default value @{common_criteria_compliance_enabled} for the 'common criteria compliance enabled' option","DefaultRuleset, Performance, Configuration","SQL Server is being developed to achieve not only the best performance results but also to be the most secure database system ever released. Microsoft has the commitment to be compliant with the most important standards. The most recent SQL Server Editions are getting these recognitions, including the Common Criteria certification. Part of that commitment is the independent third-party evaluation of our products and in using the Common Criteria (CC, ISO15408) as a proven and accepted process to ensure compliance with Common Evaluation Methodologies.","https://docs.microsoft.com/sql/database-engine/configure-windows/common-criteria-compliance-enabled-server-configuration-option","Server","Windows Linux",,"Enterprise, ManagedInstance","[11.0,)",,, "ClrEnabled","definition","TRUE","Information","Non-default value for 'clr enabled' option","Review non-default value @{clr_enabled} for the 'clr enabled' option","DefaultRuleset, Configuration","This option determines whether user assemblies and CLR functionality or objects can be used on a Microsoft SQL Server instance. Disable this option if you do not plan to use CLR database objects on the SQL Server instance.","https://docs.microsoft.com/sql/relational-databases/clr-integration/clr-integration-enabling","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "CompareRunConfigured","definition","TRUE","Information","Run and config values are different","Use 'RECONFIGURE' after 'sp_configure' to update run value. Config value is different from run value in: @{unsaved_option}","DefaultRuleset, Performance, Configuration","SQL Server instance configuration settings have two values: a run value which is the currently active value and a config value which is the value that was last configured. Generally, these two values are the same, but if a setting has been changed but the change is not yet applied, confusion can arise for administrators and, in extreme cases, the system can become unstable.","https://docs.microsoft.com/sql/relational-databases/system-catalog-views/sys-configurations-transact-sql","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "ContainedDbAuthentication","definition","TRUE","Information","Non-default value for 'contained database authentication' option","Review non-default value @{contained_database_authentication} for the 'contained database authentication' option","DefaultRuleset, Configuration, Security","When contained databases are enabled, database users other than members of the 'sysadmin' and 'securityadmin' fixed server roles can grant access to the instance of SQL Server.","https://docs.microsoft.com/sql/database-engine/configure-windows/contained-database-authentication-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "CursorThreshold","definition","TRUE","Information","Non-default value for 'cursor threshold' option","Review non-default value @{cursor_threshold} for the 'cursor threshold' option","DefaultRuleset, Performance, Configuration","When cursors generate keysets for a result set, the query optimizer estimates how many rows the keyset will contain. If the number is larger than this threshold, the keyset is generated asynchronously. The default value of -1 results in SQL Server generating all keysets asynchronously. If you set the value too low, overall performance may be impacted because small results sets are better built synchronously.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-cursor-threshold-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "DatabaseMailXPs","definition","TRUE","Information","Non-default value for 'Database Mail XPs' option","Review non-default value @{Database_Mail_XPs} for the 'Database Mail XPs' option","DefaultRuleset, Configuration, Security","Configuring the 'Database Mail XPs' option to 1 enables Database Mail on the instance of SQL Server. This configuration is off by default to reduce the attack surface area of SQL Server. Do not enable this functionality unless you intend to use Database Mail.","https://docs.microsoft.com/sql/database-engine/configure-windows/database-mail-xps-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"DbCompression","definition","TRUE","Information","Uncompressed database tables and indexes","Compress index: @{IndexName}, total space: @{TotalSpaceMB:N2} MB","DefaultRuleset, Configuration, Performance","The compression capability at either the row or page level provides an opportunity to save disk space and improve performance, with the tradeoff of requiring a bit more CPU to compress and decompress the data, but requiring less memory and disk access improving performance in many workloads. The data pages are kept compressed when they are uploaded to memory. This check fires if a relatively large amount of space is on indexes without compression (for example, more than 10GB).","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb","1280000", +"DbCompression","definition","TRUE","Information","Uncompressed database tables and indexes","Turn on compression for these @{ObjectType}: @{ObjectName}, total space used by these objects: @{TotalSpaceMB:N2} MB","DefaultRuleset, Configuration, Performance","The compression capability at either the row or page level provides an opportunity to save disk space and improve performance, with the tradeoff of requiring a bit more CPU to compress and decompress the data, but requiring less memory and disk access improving performance in many workloads. The data pages are kept compressed when they are uploaded to memory. This check fires if a relatively large amount of space is on indexes without compression (for example, more than 10GB).","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb","1280000", "DbRecoveryModel","definition","TRUE","Medium","Databases with 'SIMPLE' recovery model","Change recovery model to 'FULL' or 'BULK_LOGGED'","DefaultRuleset, Configuration","A database with the 'SIMPLE' recovery model does not support log backups. As a result, when you need to restore such a database, all the transactions since the last database backup or differential backup will be lost. Review databases that have the 'SIMPLE' recovery model. If the maximum amount of data loss involved is not acceptable, change the recovery model to 'FULL' or 'BULK_LOGGED' and schedule frequent log backups.","https://docs.microsoft.com/sql/relational-databases/backup-restore/recovery-models-sql-server","Database","Windows Linux",,"SqlServer","[11.0,)","NOT: model tempdb msdb master",, "DbSpaceAvailable","definition","TRUE","Medium","Low free space in data files","Increase space for data files. Currently @{spaceAvailableRel:P0} is available. Threshold is set to @{threshold:P0}. Total size of data files: @{totalMB:N2} MB. Free space: @{freeMB:N2} MB","DefaultRuleset, Configuration, DBFileConfiguration","Average available space in data files is less than the threshold.","https://docs.microsoft.com/sql/relational-databases/databases/database-states","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,"0.25", "DbStandby","definition","TRUE","Information","STANDBY mode is enabled","Disable STANDBY mode for database","DefaultRuleset, Configuration","A Database in STANDBY mode will be online as READ ONLY, WITH RESTORE LOG allowed. If recovery is not complete, then the availability of the database might be affected. Usually log shipped secondary databases are configured to be in STANDBY mode.","https://docs.microsoft.com/sql/t-sql/statements/restore-statements-arguments-transact-sql#with-options","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"EKMProvider","definition","TRUE","Information","Non-default value for 'EKM provider enabled' option","Review non-default value @{EKM_provider_enabled} for the 'EKM provider enabled' option","DefaultRuleset, Configuration","The 'EKM provider enabled' option controls Extensible Key Management device support in SQL Server. SQL Server provides data encryption capabilities together with Extensible Key Management (EKM), using the Microsoft Cryptographic API (MSCAPI) provider for encryption and key generation. Encryption keys for data and key encryption are created in transient key containers, and they must be exported from a provider before they are stored in the database. This approach enables key management that includes an encryption key hierarchy and key backup, to be handled by SQL Server.","https://docs.microsoft.com/sql/database-engine/configure-windows/ekm-provider-enabled-server-configuration-option","Server","Windows Linux",,"Enterprise, ManagedInstance","[11.0,)",,, +"DbState","definition","TRUE","Low","Database with unavailable state","Check '@{DbName}' database availability. Current database state is: @{DbStateDesc}","DefaultRuleset, Configuration","Database unavailability may affect expected application behavior due to the impossibility of establishing user connections. The issue occurs when a database is in any of the following states: 'RECOVERY_PENDING', 'RECOVERING', 'SUSPECT', or 'RESTORING'.","https://docs.microsoft.com/sql/relational-databases/databases/database-states","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"DisallowResultsTriggers","definition","TRUE","Information","Option 'disallow results from triggers' is disabled","Enable 'disallow results from triggers' option as the ability to return result sets from triggers will be removed in a future version","DefaultRuleset, Configuration","Use the 'disallow results from triggers' option to control whether triggers return result sets. Triggers that return result sets may cause unexpected behavior in applications that are not designed to work with them.","https://docs.microsoft.com/sql/database-engine/configure-windows/disallow-results-from-triggers-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"EKMProvider","definition","TRUE","Information","Non-default value for 'EKM provider enabled' option","Review non-default value @{EKM_provider_enabled} for the 'EKM provider enabled' option","DefaultRuleset, Configuration","The 'EKM provider enabled' option controls Extensible Key Management device support in SQL Server. SQL Server provides data encryption capabilities together with Extensible Key Management (EKM), using the Microsoft Cryptographic API (MSCAPI) provider for encryption and key generation. Encryption keys for data and key encryption are created in transient key containers, and they must be exported from a provider before they are stored in the database. This approach enables key management that includes an encryption key hierarchy and key backup, to be handled by SQL Server.","https://docs.microsoft.com/sql/database-engine/configure-windows/ekm-provider-enabled-server-configuration-option","Server","Windows Linux",,"Standard, Enterprise, ManagedInstance","[11.0,)",,, +"EKMProvider","override","False","Low",,,"",,,,,,"Standard","[11.0, 15.0)",,, +"FileMaxSize","definition","TRUE","Information","Setting 'Autogrow' for data files","Check 'autogrow' setting. Currently maximum size of @{maxsize_in_mb} MBs is set for @{type_desc} file @{fileName} in database @{databaseName}","DefaultRuleset, Performance, DBFileConfiguration","This check verifies the 'autogrow' settings of data files for all system and user databases. In SQL Server, a log file specified with unlimited growth has a maximum size of 2 TB, and a data file has a maximum size of 16 TB. There is no maximum size when this option is specified for a FILESTREAM container. It continues to grow until the disk is full. If there is no space available, performance issues may occur and the database may become unavailable.","https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-file-and-filegroup-options","Server","Windows Linux",,"SqlServer","[11.0,)",,, "FilestreamAccessLevel","definition","TRUE","Information","Non-default value for 'filestream access level' option","Review non-default value @{filestream_access_level} for the 'filestream access level' option","DefaultRuleset, Configuration","The 'filestream access level' option controls the FILESTREAM access level for the instance of SQL Server. By default, this option is disabled, but should be enabled to allow FileStream access or to take advantage of the 'FileTable' feature.","https://docs.microsoft.com/sql/database-engine/configure-windows/filestream-access-level-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FillFactor","definition","TRUE","Information","Non-default value for 'fill factor' option","Review non-default value @{fill_factor} for the 'fill factor' option","DefaultRuleset, Performance, Configuration","The 'fill factor' option controls the default fill factor that is used when a new index is created or rebuilt. The default value is 0, which means that the leaf level of the index will be filled with the highest possible number of rows. This option is an advanced option and should be changed only by an experienced database administrator or certified SQL Server professional.","https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-fill-factor-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FtCrawlBandwidthMax","definition","TRUE","Low","Non-default value for 'ft crawl bandwidth (max)' option","Review non-default value @{ft_crawl_bandwidth_max} for the 'ft crawl bandwidth (max)' option as it will be removed in a future version","DefaultRuleset, Configuration","The 'ft crawl bandwidth (max)' option determines the maximum number of buffers that will be maintained by the full-text memory manager in a small buffer pool. A high value will allocate more memory to the indexing process, therefore reducing the available memory for other SQL Server processes.","https://docs.microsoft.com/sql/database-engine/configure-windows/ft-crawl-bandwidth-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FtCrawlBandwidthMin","definition","TRUE","Low","Non-default value for 'ft crawl bandwidth (min)' option","Review non-default value @{ft_crawl_bandwidth_min} for the 'ft crawl bandwidth (min)' option as it will be removed in a future version","DefaultRuleset, Configuration","The 'ft crawl bandwidth (min)' option determines the minimum number of buffers that must be maintained by the full-text memory manager in a small buffer pool. If the SQL Server memory manager requests memory, this minimum number of buffers will generally be maintained.","https://docs.microsoft.com/sql/database-engine/configure-windows/ft-crawl-bandwidth-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FtNotifyBandwidthMax","definition","TRUE","Low","Non-default value for 'ft notify bandwidth (max)' option","Review non-default value @{ft_notify_bandwidth_max} for the 'ft notify bandwidth (max)' option as it will be removed in a future version","DefaultRuleset, Configuration","The 'ft notify bandwidth (max)' option determines the maximum number of buffers that will be maintained by the full-text memory manager in a large buffer pool. A high value will allocate more memory to the indexing process, therefore reducing the available memory for other SQL Server processes.","https://docs.microsoft.com/sql/database-engine/configure-windows/ft-notify-bandwidth-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FtNotifyBandwidthMin","definition","TRUE","Low","Non-default value for 'ft notify bandwidth (min)' option","Review non-default value @{ft_notify_bandwidth_min} for the 'ft notify bandwidth (min)' option as it will be removed in a future version","DefaultRuleset, Configuration","The 'ft notify bandwidth (min)' option determines the minimum number of buffers that must be maintained by the full-text memory manager in a large buffer pool. If the SQL Server memory manager requests memory, this minimum number of buffers will generally be maintained.","https://docs.microsoft.com/sql/database-engine/configure-windows/ft-notify-bandwidth-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"FullTextDefaultLang","definition","TRUE","Low","Not supported value for 'default full-text language' option","Set 'default full-text language' option to a supported value","DefaultRuleset, Configuration","The value of the 'default full-text language' option is used in a full-text index when no language is specified. If the default full-text language is not supported or the linguistic analysis package is not available, CREATE FULLTEXT INDEX and ALTER FULLTEXT INDEX statements will fail.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-default-full-text-language-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "FullTextNoiseWords","definition","TRUE","Information","Non-default value for 'transform noise words' option","Review non-default value @{transform_noise_words} for the 'transform noise words' option","DefaultRuleset, Configuration","If a query using a full-text search predicate contains a noise word (for example, is, the, and) and this configuration setting has been disabled, a warning will be issued and no rows from the query will be returned. The default setting for this option is 0, which indicates that it is off. Enabling this configuration by changing the default to 1 will force noise words to be replaced with an asterisk (*) in the query instead.","https://docs.microsoft.com/sql/database-engine/configure-windows/transform-noise-words-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"FullTextPHTimeout","definition","TRUE","Information","Non-default value for 'PH timeout' option","Set 'PH timeout' option to default","DefaultRuleset, Configuration","The 'PH timeout' option controls the number of seconds that the full-text protocol handler will wait to connect to a database before reaching the timeout threshold. You can increase the 'PH timeout' value when connection attempts are timing out due to temporary network issues.","https://docs.microsoft.com/sql/database-engine/configure-windows/ph-timeout-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"FullTextPHTimeout","definition","TRUE","Information","Non-default value for 'PH timeout' option","Review non-default value @{PH_timeout} for the 'PH timeout' option","DefaultRuleset, Configuration","The 'PH timeout' option controls the number of seconds that the full-text protocol handler will wait to connect to a database before reaching the timeout threshold. You can increase the 'PH timeout' value when connection attempts are timing out due to temporary network issues.","https://docs.microsoft.com/sql/database-engine/configure-windows/ph-timeout-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "InDoubtXactResolution","definition","TRUE","Information","Non-default value for 'in-doubt xact resolution' option","Review non-default value @{in_doubt_xact_resolution} for the 'in-doubt xact resolution' option","DefaultRuleset, Configuration","The 'in-doubt xact resolution' option controls the default outcome of unresolved Microsoft Distributed Transaction Coordinator (MS DTC) transactions. The default value of 0 means that recovery will fail if MS DTC cannot resolve the in-doubt transactions. Before changing this default, you should consider the effect of your application distributed transactions and make sure that no data integrity issues will occur based on partially committed or aborted activity.","https://docs.microsoft.com/sql/database-engine/configure-windows/in-doubt-xact-resolution-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, -"InstantFileInitialization","definition","TRUE","High","Instant file initialization (IFI) is disabled","Enable instant file initialization","DefaultRuleset, DBConfiguration, Performance","Instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Instead, disk content is overwritten as new data is written to the files.","https://docs.microsoft.com/en-us/sql/relational-databases/databases/database-instant-file-initialization","Server","Windows",,"SqlServer","[11.0.7001,12.0) [12.0.5000, )",,, +"InstantFileInitialization","definition","TRUE","High","Instant file initialization (IFI) is disabled","Enable instant file initialization","DefaultRuleset, DBConfiguration, Performance","Instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Instead, disk content is overwritten as new data is written to the files.","https://docs.microsoft.com/en-us/sql/relational-databases/databases/database-instant-file-initialization","Server","Windows",,"SqlServer","[11.0.7001,12.0) [12.0.6024,13.0) [13.0.4001,)",,, "JdbcModuleVersion","definition","TRUE","Medium","JDBC Driver for SQL Server version is not supported","Update JDBC Driver for SQL Server. Current product version @{file_version} of JDBC Driver for SQL Server is out of support","DefaultRuleset, Performance, Security","The JDBC Driver for SQL Server is a Type 4 Java Database Connectivity (JDBC) 4.2 compliant driver that provides robust data access to SQL Server, Azure SQL Database, and Azure SQL Managed Instance. Java connectivity support is continually improving. It is highly recommend to use the latest version of JDBC driver for SQL Server.","https://docs.microsoft.com/sql/connect/jdbc/understanding-xa-transactions","Server","Windows Linux",,"SqlServer","[11.0,)",,, "LockedPagesInMemory","definition","TRUE","High","Lock pages in memory","Enable the 'Lock pages in memory' option","DefaultRuleset, Performance, Memory","This Windows policy determines which accounts can use a process to keep data in physical memory, preventing the system from paging the data to virtual memory on disk.","https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist","Server","Windows","AzureVm","SqlServer","[11.0,)",,, "LockedPagesInMemory","override","TRUE","Low",,,"",,,,,,,"[11.0.7001, 12.0) [12.0.6024, 13.0) [13.0.4001,)",,, @@ -277,6 +294,7 @@ "MaxTextReplSize","definition","TRUE","Information","Non-default value for 'max text repl size' option","Review non-default value @{max_text_repl_size} for the 'max text repl size' option","DefaultRuleset, Configuration","The 'max text repl size' option sets the maximum bytes of varchar(max), nvarchar(max), varbinary(max), xml, image, text, and ntext data that can be replicated in a single INSERT, UPDATE, WRITETEXT, or UPDATETEXT operation. If your data modifications exceed this value on replicated columns, you must increase it.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-max-text-repl-size-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "MediaRetention","definition","TRUE","Information","Non-default value for 'media retention' option","Review non-default value @{media_retention} for the 'media retention' option","DefaultRuleset, Configuration, Backup","The 'media retention' option sets the default length of time to retain a backup set for the Microsoft SQL Server instance. This default length of time protects the set from being overwritten until the specified number of days has elapsed. The default for this configuration is 0 days. However, you can modify it, based on your own corporate policies.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-media-retention-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "MemOptDBResPool","definition","TRUE","Low","In-Memory OLTP database without separate resource pool","Bind In-Memory OLTP database to separate resource pool","Memory, Performance, DefaultRuleset","A databases with memory-optimized tables should be bound to a separate resource pool.","https://docs.microsoft.com/sql/relational-databases/in-memory-oltp/bind-a-database-with-memory-optimized-tables-to-a-resource-pool#bkmk_DefineBinding","Database",,,"SqlServer","[12.0,)",,, +"MoreIndexesThanCols","definition","TRUE","Information","Tables with more indexes than columns","Consider removing potentially unnecessary indexes on table @{SchemaName}.@{TableName} that has more indexes than columns","DefaultRuleset, Performance, Indexes","One or more database tables have been identified as having more indexes than columns. During inserts, updates and deletes, every index on a table has to be evaluated and, potentially, updated. If too many indexes exist, SQL Server will spend unnecessary resources maintaining indexes that may not be used. This can significantly affect the amount of disk I/O generated and, subsequently, performance.","https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide","Database","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)","NOT: master model msdb tempdb",, "OneDbPerPool","definition","TRUE","Low","One database per resource pool","Check whether only one database is bound to resource pool @{pool_name}","Memory, Performance, DefaultRuleset","Only one database should be bound to a resource pool.","https://docs.microsoft.com/sql/relational-databases/resource-governor/resource-governor-resource-pool","Database",,,"SqlServer","[12.0,)",,, "OpenObjects","definition","TRUE","Low","Non-default value for 'open objects' option","Review non-default value @{open_objects} for the 'open objects' option as it has no effect and will be removed in a future version","DefaultRuleset, Performance, Configuration","The 'open objects' option has no effect and will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.","https://docs.microsoft.com/sql/database-engine/configure-windows/open-objects-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "OsLoadedModules","definition","TRUE","Low","Third-party modules are loaded into SQL Server process address space","Evaluate impact of loading '@{module}' module into SQL Server process address space","DefaultRuleset, Performance, Security","Certain modules and filter drivers can be loaded into a system that is running SQL Server. In this case, you may experience performance degradation and consistency issues of SQL Server Database Engine.","https://docs.microsoft.com/troubleshoot/sql/performance/performance-consistency-issues-filter-drivers-modules","Server","Windows",,"SqlServer","[11.0,)",,, @@ -289,6 +307,7 @@ "ReplicationXPs","definition","TRUE","Low","Non-default value for 'Replication XPs' option","Set 'Replication XPs' option to default. This option is for internal use only.","DefaultRuleset, Configuration, Security","The 'Replication XPs' option opens a significant attack surface area that can be used by an attacker to gather information about the system and potentially abuse the privileges of SQL Server.","https://docs.microsoft.com/sql/database-engine/configure-windows/replication-xps-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "SMOAndDMOXPs","definition","TRUE","Information","Option 'SMO and DMO XPs' is disabled","Enable 'SMO and DMO XPs' option","DefaultRuleset, Configuration","The 'SMO and DMO XPs' option determines whether SQL Server Management Objects (SMO) and SQL Server Distributed Management Objects (SQL-DMO) XPs are available. The default for this option is enabled to allow various tools and install packages, including SQL Server hotfixes, to work correctly.","https://docs.microsoft.com/sql/database-engine/configure-windows/smo-and-dmo-xps-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "SysAdminDefaultDatabase","definition","TRUE","Low","Sysadmin logins use non-master default database","Set sysadmin logins to use 'master' as default database","DefaultRuleset, Configuration","This check verifies whether your SQL Sever logins are members of the 'System Administrators' role that use a non-master default database. Sysadmin logins that use a non-master default database impose administrative risks in cases when user databases are dropped.",,"Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, +"TempDbSameVolume","definition","TRUE","Medium","Tempdb and user databases should not share volumes","Place tempdb on a separate volume. Tempdb and user databases share volume @{volume_mount_point}","DefaultRuleset, Performance, DBFileConfiguration","The tempdb system database is used for temporary objects, internal objects and row versions. Tempdb is often heavily used when queries are executed and, if it has files placed on the same volume as user database files, there can be contention for the IO resources.","https://docs.microsoft.com/sql/relational-databases/databases/tempdb-database","Database","Windows","@{not=AzureVm}","SqlServer","[11.0,)","tempdb",, "TwoDigitYearCutoff","definition","TRUE","Information","Non-default value for 'two digit year cutoff' option","Set 'two digit year cutoff' option to default","DefaultRuleset, Configuration","The 'two digit year cutoff' option is used to define the two digit year cutoff value when specifying two-digit years in place of four-digit years. Changing this to a non-default value could have unexpected results if the non-default value is inconsistent with other Microsoft SQL Server instances in your environment. This option is an advanced option and should be changed only by an experienced database administrator or certified SQL Server professional.","https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-two-digit-year-cutoff-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "UserConnections","definition","TRUE","Information","Non-default value for 'user connections' option","Review non-default value @{user_connections} for the 'user connections' option","DefaultRuleset, Performance, Configuration","The 'user connections' option is an advanced option and should be changed only by an experienced database administrator or certified SQL Server professional. Using the 'user connections' option helps avoid overloading the server with too many concurrent connections. You can estimate the number of connections based on system and user requirements.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-user-connections-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, "UserOptions","definition","TRUE","Information","Non-default value for 'user options' option","Review non-default value @{user_options} for the 'user options' option","DefaultRuleset, Configuration","The 'user options' option defines the user option defaults, such as ARITHABORT, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL. The bit positions in user options are identical to those in @@OPTIONS. Each connection has its own @@OPTIONS function, which represents the configuration environment. When logging in to Microsoft SQL Server, a user receives a default environment that assigns the current user options value to @@OPTIONS. Executing SET statements for user options affects the corresponding value in the session's @@OPTIONS function. All connections created after this setting is changed, receive the new value.","https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-user-options-server-configuration-option","Server","Windows Linux",,"SqlServer, ManagedInstance","[11.0,)",,, diff --git a/samples/manage/sql-assessment-api/release-notes.md b/samples/manage/sql-assessment-api/release-notes.md index 1e1d8a0e..8ce8d96f 100644 --- a/samples/manage/sql-assessment-api/release-notes.md +++ b/samples/manage/sql-assessment-api/release-notes.md @@ -14,6 +14,86 @@ Download: [SMO NuGet Package](https://www.nuget.org/packages/Microsoft.SqlServer You can use GitHub issues to provide feedback to the product team. +## July 2022 - 1.1.9 + +Version: SqlServer PowerShell module, SqlManagementObjects (SMO) package: not updated + +### What's new + +- New rules: + - Access check cache options ratio + - Availability group listener network mode + - Availability group failure-condition level + - Availability group health check timeout + - Availability replica connection state + - Availability replica synchronization health + - Availability database automatic failover readiness + - Availability database joined state + - Azure data disk striping + - Database mirroring endpoint encryption + - Database with unavailable state + - Maximum number of Availability Groups + - Not supported value for 'default full-text language' option + - Non-default values for access check cache options + - Option 'disallow results from triggers' is disabled + - Setting 'Autogrow' for data files + - Tables with more indexes than columns + - TempDb and user databases should not share volumes +- New Probes: + - AGConfiguration + - AGDatabases + - AGEndpoints + - AGListener + - DatabaseSharedVolumes + - DatabasesState + - SysFullTextLanguages + - TablesInformation +- Added 'MaxCheckResults' configuration option to limit assessment output + +### Bug fixes and improvements + +- The following rules are not run for Linux targets now: + - Indexes keys with more than @{threshold} bytes + - MAXDOP set in accordance with CPU count + - 'STRelate' and 'STAsBinary' functions unexpected results due to TF 6533 + - TF 4199 enables query optimizer fixes + - TF 6532 enables performance improvements for spatial data + - TF 8015 disables auto-detection and NUMA setup + - TF 8744 disables pre-fetching for Nested Loop operator + - TF 9347 disables batch mode for sort operator + - TF 9349 disables batch mode for top N sort operator + - TF 9389 enables dynamic memory grant for batch mode operators + - TF 9476 causes SQL Server to generate plan using Simple Containment assumption + - TF 9481 enables Legacy CE model +- Improved performance of idex related probes and checks +- Improved performance of other probes +- Affinity 64 and Affinity 64 IO masks are checked on 64-bit platforms only +- Instant File Initialization check is not run for SQL Server 2016 without service packs +- Fixed requirements processing for checks +- 'Max allowed memory' and 'Max server memory exceeds system memory' checks are not run for SQL Server Managed Instance now +- Updated 'Latest cumulative update' check +- 'Stored procedure naming' check severity changed to Low +- 'Uncompressed database tables and indexes' gives more details in the message +- 'SQL logins have weak passwords' now checks for empty passwords and password equal to login +- Non-default value for 'common criteria compliance enabled' option +- Option 'backup compression default' is disabled +- Replaced DatabaseFileLocation probe with DatabaseMasterFiles in the following rules: + - Azure disk caching for data files + - Azure disk caching for transaction logs + - Data files on Azure data disks + - Storage spaces disk column count + - Tempdb files on Azure temp drive + - Use premium SSDs for SQL Server data files +- Improved probes + - OsSysMemory + - ServerProperties + - TopUncompressedTables + - ServerProperties + - WeakPassword +- Removed rules: + - LoginEqPassword + - LoginNoPassword + ## December 2021 - 1.1.0 Version: SqlServer PowerShell module, SqlManagementObjects (SMO) package: not updated diff --git a/samples/manage/sql-assessment-api/ruleset.json b/samples/manage/sql-assessment-api/ruleset.json index 1cf77817..7ca2313b 100644 --- a/samples/manage/sql-assessment-api/ruleset.json +++ b/samples/manage/sql-assessment-api/ruleset.json @@ -1,7 +1,7 @@ { "schemaVersion": "1.0", "name": "Microsoft ruleset", - "version": "1.0.306", + "version": "1.1.9", "rules": [ { "id": "AutoCreateStats", @@ -767,12 +767,6 @@ "targetFilter": { "version": "[12.0, )" }, - "tags": [ - "DefaultRuleset", - "TraceFlag", - "QueryOptimizer", - "Performance" - ], "message": "TF2312 sets the query optimizer cardinality estimation model to SQL Server 2014 or above versions, dependent of the compatibility level of the database", "level": "Information", "enabled": false @@ -1400,10 +1394,7 @@ "target": { "type": "Server", "version": "[11.0, 14.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -1469,10 +1460,7 @@ "target": { "type": "Server", "version": "[11.0.6020,11.0.6518)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -2106,7 +2094,7 @@ "version": [ "[11.0.7001, 12.0)", "[12.0.6024, 13.0)", - "[13.0.5026,)" + "[13.0.6300,)" ] }, "displayName": "SQL Server instance is not up to date", @@ -2119,16 +2107,26 @@ "targetFilter": { "version": [ "[11.0.7507, 12.0)", - "[12.0.6433, 13.0)", - "[13.0.6300, 14.0)", - "[14.0.3430, 15.0)", - "[15.0.4198,)" + "[12.0.6439, 13.0)", + "[13.0.6419, 14.0)", + "[14.0.3445, 15.0)", + "[15.0.4236,)" ] }, "displayName": "SQL Server instance is up to date", "message": "Product version @{ProductVersion} is latest available", "condition": true }, + { + "id": "LatestCU", + "itemType": "override", + "targetFilter": { + "version": "[11.0, 12.0)" + }, + "description": "We recommend upgrading to the latest SQL Server version to keep your instances secure and compliant. If upgrade is not an option at this point, follow the help link to protect your SQL Server 2012 with Extended Security Updates (ESU).", + "message": "Upgrade SQL Server 2012 to receive full product updates and Microsoft Support. End of support is July, 12 2022.", + "helpLink": "https://docs.microsoft.com/sql/sql-server/end-of-support/sql-server-extended-security-updates" + }, { "id": "FKNoIndexes", "itemType": "definition", @@ -2156,14 +2154,22 @@ ], "displayName": "Foreign key constraints should have corresponding indexes", "description": "Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index. However, manually creating an index on a foreign key is often useful.", - "message": "Create a corresponding index for each foreign key. There is no index on foreign keys: @{ConstraintName}", + "message": "Create a corresponding index on each foreign key in tables: @{TableName}", "helpLink": "https://docs.microsoft.com/sql/relational-databases/tables/primary-and-foreign-key-constraints", "level": "Medium", - "condition": { - "@ConstraintName": "" - }, "probes": [ - "FKNoIndexes" + { + "id": "FKNoIndexes", + "transform": { + "type": "aggregate", + "map": { + "TableName": { + "type": "join", + "limit": 10 + } + } + } + } ] }, { @@ -2896,7 +2902,7 @@ ], "displayName": "Duplicate indexes", "description": "A SQL Server index is an on-disk or in-memory structure associated with a table or view that speeds retrieval of rows from the table or view. An index contains keys built from one or more columns in the table or view. ", - "message": "Remove duplicate indexes in table @{Table}: @{ToDelete}", + "message": "Remove duplicate indexes in table @{Table}: @{Indexes}", "helpLink": "https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide", "level": "Low", "probes": [ @@ -3482,8 +3488,15 @@ "message": "Set strong passwords for logins: @{PasswordData}", "helpLink": "https://docs.microsoft.com/sql/relational-databases/security/strong-passwords", "level": "Medium", + "condition": "@is_integrated_security_only", "probes": [ - "WeakPassword" + "ServerProperties", + { + "id": "WeakPassword", + "params": { + "is_disabled": 0 + } + } ] }, { @@ -3536,10 +3549,7 @@ "target": { "type": "Server", "version": "[11.0,11.0.3349)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3604,10 +3614,7 @@ "target": { "type": "Server", "version": "[11.0,12.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3638,10 +3645,7 @@ "target": { "type": "Server", "version": "[11.0,13.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3671,10 +3675,7 @@ "target": { "type": "Server", "version": "[11.0,13.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3704,10 +3705,7 @@ "target": { "type": "Server", "version": "[11.0,13.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer, ManagedInstance" }, "tags": [ @@ -3738,10 +3736,7 @@ "target": { "type": "Server", "version": "[11.0,13.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3772,10 +3767,7 @@ "target": { "type": "Server", "version": "[11.0,12.0)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "engineEdition": "SqlServer" }, "tags": [ @@ -3855,7 +3847,7 @@ "description": "In SQL Server, the sp_ prefix designates system stored procedures. If you use that prefix for your stored procedures, the name of your procedure might conflict with the name of a system stored procedure that will be created in the future. If such a conflict occurs, your application might break if your application refers to the procedure without qualifying the reference by schema. In this situation, the name will bind to the system procedure instead of to your procedure.", "message": "Rename the following stored procedures to eliminate 'sp_' prefix: @{ObjectName}", "helpLink": "https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172115(v=vs.100)", - "level": "Medium", + "level": "Low", "condition": { "not": "@ObjectName" }, @@ -4151,10 +4143,7 @@ "itemType": "definition", "target": { "type": "Database", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "name": { "not": [ "master", @@ -4615,58 +4604,6 @@ "TableIndexesPartitioned" ] }, - { - "id": "LoginNoPassword", - "itemType": "definition", - "target": { - "type": "Server", - "platform": [ - "Windows", - "Linux" - ], - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "tags": [ - "DefaultRuleset", - "Security", - "WeakPassword" - ], - "displayName": "SQL logins have no passwords", - "enabled": false, - "description": "Password complexity policies are designed to deter brute force attacks by increasing the number of possible passwords. Make sure that you use a strong password for each of your SQL logins to decrease vulnerabilities.", - "message": "Set strong passwords for logins: @{PasswordData}", - "helpLink": "https://docs.microsoft.com/sql/relational-databases/security/password-policy", - "probes": [ - "NullPassword" - ] - }, - { - "id": "LoginEqPassword", - "itemType": "definition", - "target": { - "type": "Server", - "platform": [ - "Windows", - "Linux" - ], - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "tags": [ - "DefaultRuleset", - "Security", - "WeakPassword" - ], - "displayName": "Passwords and SQL login names are the same", - "enabled": false, - "description": "Password complexity policies are designed to deter brute force attacks by increasing the number of possible passwords. Make sure that you use passwords that are different from your SQL login names.", - "message": "Review logins that have passwords equal to SQL login names: @{PasswordData}", - "helpLink": "https://docs.microsoft.com/sql/relational-databases/security/password-policy", - "probes": [ - "NamePassword" - ] - }, { "id": "SystemHealth", "itemType": "definition", @@ -5018,10 +4955,7 @@ "target": { "type": "Server", "engineEdition": "SqlServer", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "version": "[11.0, 13.0)" }, "tags": [ @@ -5604,10 +5538,7 @@ "target": { "type": "Database", "version": "[11.0.6020, 11.0.6518)", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "name": { "not": [ "master", @@ -5853,7 +5784,7 @@ ], "displayName": "Affinity Mask and Affinity I/O Mask overlapping", "description": "Enabling a CPU with both the affinity mask and the affinity I/O mask can slow performance by forcing the processor to be overused. When specified either the affinity mask or the affinity I/O mask options they must both be specified, but only enables each CPU no more than once. The same CPU should not be enabled in both the affinity mask option and the affinity I/O mask option. The bits that correspond to each CPU should be in one of the following states.", - "message": "Correct Affinity Mask and Affinity IO Mask overlap. AffinityMask = @{affinity_mask}, Affinity64Mask = @{affinity64_mask}, AffinityIOMask = @{affinity_io_mask}, Affinity64IOMask = @{affinity64_io_mask}", + "message": "Correct Affinity Mask and Affinity IO Mask overlap", "helpLink": "https://docs.microsoft.com/sql/relational-databases/policy-based-management/correct-affinity-mask-and-affinity-input-and-output-mask-overlap", "level": "Low", "condition": { @@ -5870,20 +5801,31 @@ ] }, { - "eq": [ + "or": [ { - "bitand": [ - "@affinity64_mask", - "@affinity64_io_mask" + "ne": [ + "@architecture", + 64 ] }, - 0 + { + "eq": [ + { + "bitand": [ + "@affinity64_mask", + "@affinity64_io_mask" + ] + }, + 0 + ] + } ] } ] }, "probes": [ - "SysConfiguration" + "SysConfiguration", + "ServerProperties" ] }, { @@ -7147,10 +7089,7 @@ "target": { "type": "Server", "engineEdition": "SqlServer", - "platform": [ - "Windows", - "Linux" - ], + "platform": "Windows", "version": "[11.0, 13.0)" }, "tags": [ @@ -7213,7 +7152,7 @@ "Windows", "Linux" ], - "engineEdition": "SqlServer, ManagedInstance", + "engineEdition": "SqlServer", "version": "[11.0,)" }, "tags": [ @@ -7342,7 +7281,7 @@ "Windows", "Linux" ], - "engineEdition": "SqlServer, ManagedInstance", + "engineEdition": "SqlServer", "version": "[11.0,)" }, "tags": [ @@ -7560,9 +7499,17 @@ "probes": [ "NtfsBlockSize", { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": null + "type": null, + "dbId": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } } ] @@ -7599,15 +7546,23 @@ "probes": [ "NtfsBlockSize", { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": null + "type": null, + "dbId": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" } } ] @@ -8537,6 +8492,83 @@ "SysConfiguration" ] }, + { + "id": "AccessCheckCache", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "Configuration" + ], + "displayName": "Non-default values for access check cache options", + "description": "When database objects are accessed by SQL Server, the access check is cached in an internal structure called the access check result cache. The 'access check cache bucket count' and 'access check cache quota' options control the number of hash buckets and number of entries used for access check result cache. The default values of 0 indicate that SQL Server is managing these options.", + "message": "Review non-default values for access check cache options", + "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/access-check-cache-server-configuration-options", + "level": "Information", + "condition": { + "and": [ + { + "eq": [ + "@access_check_cache_quota", + 0 + ] + }, + { + "eq": [ + "@access_check_cache_bucket_count", + 0 + ] + } + ] + }, + "probes": [ + "SysConfiguration" + ] + }, + { + "id": "AccessCheckCacheRatio", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "Configuration" + ], + "displayName": "Access check cache options ratio", + "description": "When database objects are accessed by SQL Server, the access check is cached in an internal structure called the access check result cache. The 'access check cache bucket count' and 'access check cache quota' options control the number of hash buckets and number of entries used for access check result cache. These options should be set using a ratio of 1:4.", + "message": "Use a ratio of 1:4 for access check cache options", + "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/access-check-cache-server-configuration-options", + "level": "Low", + "condition": { + "eq": [ + "@access_check_cache_quota", + { + "mul": [ + 4, + "@access_check_cache_bucket_count" + ] + } + ] + }, + "probes": [ + "SysConfiguration" + ] + }, { "id": "Affinity64IOMask", "itemType": "definition", @@ -8560,13 +8592,24 @@ "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/affinity64-input-output-mask-server-configuration-option", "level": "Information", "condition": { - "eq": [ - "@affinity64_io_mask", - 0 + "or": [ + { + "ne": [ + "@architecture", + 64 + ] + }, + { + "eq": [ + "@affinity64_io_mask", + 0 + ] + } ] }, "probes": [ - "SysConfiguration" + "SysConfiguration", + "ServerProperties" ] }, { @@ -8592,13 +8635,24 @@ "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/affinity64-mask-server-configuration-option", "level": "Low", "condition": { - "eq": [ - "@affinity64_mask", - 0 + "or": [ + { + "ne": [ + "@architecture", + 64 + ] + }, + { + "eq": [ + "@affinity64_mask", + 0 + ] + } ] }, "probes": [ - "SysConfiguration" + "SysConfiguration", + "ServerProperties" ] }, { @@ -8665,6 +8719,73 @@ "SysConfiguration" ] }, + { + "id": "AGDbDisjoined", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availability database joined state", + "description": "To add a database to an availability group, the database must be an online, read-write database that exists on the server instance that hosts the primary replica. When you add a database, it joins the availability group as a primary database. No corresponding secondary database exists until backups of the new primary database are restored to the server instance that hosts the secondary replica. The new secondary database is in the RESTORING state until it is joined to the availability group. Joining places the secondary database into the ONLINE state and initiates data synchronization with the corresponding primary database.", + "message": "Join database '@{databaseName}' to availability group '@{ag_name}' on secondary replica '@{ag_replica_server}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/join-a-secondary-database-to-an-availability-group-sql-server", + "condition": { + "or": [ + { + "or": [ + { + "ne": [ + "@AGConfiguration::replica_id", + "@AGDatabases::replica_id" + ] + }, + { + "ne": [ + "@is_ag_replica_local", + 0 + ] + } + ] + }, + "@is_database_joined" + ] + }, + "probes": [ + "AGDatabases", + "AGConfiguration" + ] + }, + { + "id": "AGEndpointEncryption", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "displayName": "Database mirroring endpoint encryption", + "description": "By default, a database mirroring endpoint requires encryption of data sent over mirroring connections. In this case, the endpoint can connect only to endpoints that also use encryption. Unless you can guarantee that your network is secure, we recommend that you require encryption for your database mirroring connections.", + "message": "Configure data encryption on endpoint '@{endpoint_name}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/prereqs-restrictions-recommendations-always-on-availability", + "condition": "@is_encryption_enabled", + "probes": [ + "AGEndpoints" + ] + }, { "id": "AgentXPs", "itemType": "definition", @@ -8691,6 +8812,331 @@ "SysConfiguration" ] }, + { + "id": "AGFailureConditionLevel", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availability group failure-condition level", + "description": "A flexible failover policy provides granular control over the conditions that cause automatic failover for an availability group. By changing the failure conditions that trigger an automatic failover and the frequency of health checks, you can increase or decrease the likelihood of an automatic failover to support your Service Level Agreement (SLA) for high availability.", + "message": "Review failure-condition level for availability group '@{ag_name}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/configure-flexible-automatic-failover-policy", + "level": "Information", + "condition": { + "or": [ + { + "or": [ + { + "ne": [ + "@ag_replica_role", + 1 + ] + }, + "@is_distributed" + ] + }, + { + "eq": [ + "@failure_condition_level", + 3 + ] + } + ] + }, + "probes": [ + "AGConfiguration" + ] + }, + { + "id": "AGHealthCheckTimeout", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availability group health check timeout", + "description": "The Always On resource DLL monitors the status of internal SQL Server components. sp_server_diagnostics reports the health of these components on an interval controlled by health check timeout. The default settings are optimized for quickly reacting to symptoms of hard failures and limiting downtime, but these settings can also be overly aggressive for certain workloads and configurations.", + "message": "Review non-default value @{health_check_timeout} of health check timeout for availability group '@{ag_name}'. Default value is 30000 milliseconds (30 seconds)", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/availability-group-lease-healthcheck-timeout", + "level": "Information", + "condition": { + "or": [ + { + "or": [ + { + "ne": [ + "@ag_replica_role", + 1 + ] + }, + "@is_distributed" + ] + }, + { + "eq": [ + "@health_check_timeout", + 30000 + ] + } + ] + }, + "probes": [ + "AGConfiguration" + ] + }, + { + "id": "AGIsFailoverReady", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availability database automatic failover readiness", + "description": "Within the context of an availability group, the primary role and secondary role of availability replicas are typically interchangeable in a process known as failover. During the failover, a qualified secondary replica takes over the primary role, recovers its databases, and brings them online as the new primary databases. An automatic failover causes a qualified secondary replica to automatically transition to the primary role after the primary replica becomes unavailable.", + "message": "Database '@{databaseName}' in availability group '@{ag_name}' is not ready for automatic failover. Synchronize database on secondary replica '@{ag_replica_server}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/failover-and-failover-modes-always-on-availability-groups#AutomaticFailover", + "condition": { + "or": [ + { + "or": [ + { + "ne": [ + "@AGConfiguration::replica_id", + "@AGDatabases::replica_id" + ] + }, + { + "ne": [ + "@AGConfiguration::failover_mode", + 0 + ] + }, + { + "ne": [ + "@AGConfiguration::availability_mode", + 1 + ] + }, + { + "ne": [ + "@is_ag_replica_local", + 0 + ] + } + ] + }, + "@is_failover_ready" + ] + }, + "probes": [ + "AGConfiguration", + "AGDatabases" + ] + }, + { + "id": "AGMultipleDHCPListenerSubnets", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "displayName": "Availability group listener network mode", + "description": "DHCP network mode is limited to a single subnet that is used for every server instances that hosts a replica in the availability group. To create an availability group across multiple subnets, each subnet requires a static IP address in the listener configuration.", + "message": "Reconfigure '@{dns_name}' listener for '@{ag_name}' availability group. Use static IP addresses across multiple subnets", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/create-or-configure-an-availability-group-listener-sql-server", + "condition": { + "or": [ + { + "or": [ + { + "not": "@is_dhcp" + }, + { + "ne": [ + "@ag_id", + "@group_id" + ] + } + ] + }, + { + "eq": [ + "@network_subnet_ip", + 1 + ] + } + ] + }, + "probes": [ + { + "id": "AGListener", + "transform": { + "type": "aggregate", + "group": [ + "group_id", + "listener_id", + "dns_name" + ], + "map": { + "is_dhcp": "or", + "network_subnet_ip": "count" + } + } + }, + { + "id": "AGConfiguration", + "transform": { + "type": "aggregate", + "group": [ + "ag_id", + "ag_name" + ] + } + } + ] + }, + { + "id": "AGReplicasDisconnected", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availability replica connection state", + "description": "An availability group supports a replicated environment for a discrete set of user databases, known as availability databases. Each set of availability databases is hosted by an availability replica. Two types of availability replicas exist: a single primary replica, which hosts the primary databases, and one to eight secondary replicas, each of which hosts a set of secondary databases and serves as potential failover targets for the availability group. The primary replica sends transaction log records of each primary database to every secondary database. This process - known as data synchronization - occurs at the database level. Every secondary replica caches the transaction log records and then applies them to its corresponding secondary database.", + "message": "Resolve connection issue on availability replica '@{ag_replica_server}' in availability group '@{ag_name}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server", + "condition": { + "or": [ + { + "not": "@is_on_primary_replica" + }, + "@ag_replica_connected_state" + ] + }, + "probes": [ + "AGConfiguration" + ] + }, + { + "id": "AGReplicasSynchronized", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Availablity replica synchronization health", + "description": "An availability group supports a replicated environment for a discrete set of user databases, known as availability databases. Each set of availability databases is hosted by an availability replica. Two types of availability replicas exist: a single primary replica, which hosts the primary databases, and one to eight secondary replicas, each of which hosts a set of secondary databases and serves as potential failover targets for the availability group. The primary replica sends transaction log records of each primary database to every secondary database. This process - known as data synchronization - occurs at the database level. Every secondary replica caches the transaction log records and then applies them to its corresponding secondary database.", + "message": "Resolve synchronization issues on availability replica '@{ag_replica_server}' in availability group '@{ag_name}'", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server", + "condition": { + "or": [ + { + "not": "@is_on_primary_replica" + }, + { + "eq": [ + "@ag_replica_synchronization_health", + 2 + ] + } + ] + }, + "probes": [ + "AGConfiguration" + ] + }, + { + "id": "AGTotalNumber", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "AlwaysOn" + ], + "displayName": "Maximum number of Availability Groups", + "description": "The actual number of databases and availability groups you can put on a computer (VM or physical) depends on the hardware and workload, but there is no enforced limit. Microsoft has tested up to 10 AGs and 100 DBs per physical machine. Signs of overloaded systems can include, but are not limited to, worker thread exhaustion, slow response times for availability group system views and DMVs, and/or stalled dispatcher system dumps.", + "message": "Review the number of Availability Groups (@{ag_id}) currently hosted on the SQL Server instance", + "helpLink": "https://docs.microsoft.com/sql/database-engine/availability-groups/windows/prereqs-restrictions-recommendations-always-on-availability#PrerequisitesForAGs", + "threshold": 10, + "condition": { + "le": [ + "@ag_id", + "@threshold" + ] + }, + "probes": [ + { + "id": "AGConfiguration", + "transform": { + "type": "aggregate", + "map": { + "ag_id": "count" + } + } + } + ] + }, { "id": "AllowUpdates", "itemType": "definition", @@ -8831,15 +9277,23 @@ }, "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": 0 + "type": 0, + "is_percent_growth": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" } }, { @@ -8850,6 +9304,74 @@ } ] }, + { + "id": "AzDataDiskStriping", + "itemType": "definition", + "target": { + "type": "Server", + "platform": "Windows", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "machineType": "AzureVm" + }, + "tags": [ + "DefaultRuleset", + "Configuration", + "Performance" + ], + "displayName": "Azure data disk striping", + "description": "There are throughput and bandwidth limits at the data disk level. Applications that consume resources beyond these limits will be throttled. For more throughput and bandwidth, you can add additional data disks and use disk striping. You can use Storage Spaces inside a virtual machine to combine multiple data disks, creating more storage capacity or performance than is available from a single data disk.", + "message": "Consider using data disk striping to increase I/O bandwidth of volume @{volume_mount_point}", + "helpLink": "https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-storage#disk-striping", + "level": "Information", + "condition": { + "or": [ + { + "not": "@isData" + }, + "@isPoolDisk" + ] + }, + "probes": [ + { + "id": "DatabaseMasterFiles", + "alias": "db_files", + "params": { + "dbId": null, + "type": null + }, + "transform": [ + { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] + }, + { + "type": "aggregate", + "group": "volume_id", + "map": { + "volume_mount_point": "join" + } + } + ] + }, + { + "id": "AzStorage", + "params": { + "path": "@db_files::volume_id" + }, + "transform": { + "type": "aggregate", + "group": "isData", + "map": { + "isPoolDisk": "and" + } + } + } + ] + }, { "id": "AzDataOnDataDisks", "itemType": "definition", @@ -8885,15 +9407,23 @@ }, "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": 0 + "type": 0, + "is_percent_growth": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" } } ] @@ -8995,15 +9525,23 @@ }, "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": null + "type": null, + "dbId": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" }, "transform": { "type": "aggregate", @@ -9086,15 +9624,23 @@ }, "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": 0 + "type": 0, + "is_percent_growth": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" } }, { @@ -9142,15 +9688,23 @@ "condition": "@isTemp", "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": null + "type": null, + "is_percent_growth": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" }, "transform": { "type": "aggregate", @@ -9199,15 +9753,23 @@ }, "probes": [ { - "id": "DatabaseFilesLocation", + "id": "DatabaseMasterFiles", "params": { - "type": 1 + "type": 1, + "is_percent_growth": null + }, + "transform": { + "type": "aggregate", + "group": [ + "volume_mount_point", + "volume_id" + ] } }, { "id": "AzStorage", "params": { - "path": "@DatabaseFilesLocation::volume_id" + "path": "@DatabaseMasterFiles::volume_id" } }, { @@ -9218,6 +9780,34 @@ } ] }, + { + "id": "BackupCompression", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "Standard, Enterprise, ManagedInstance", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "displayName": "Option 'backup compression default' is disabled", + "description": "The 'backup compression default' option determines whether the server instance creates compressed backups by default. Because a compressed backup is smaller than an uncompressed backup of the same data, compressing a backup typically requires less device I/O and therefore usually increases backup speed significantly.", + "message": "Enable 'backup compression default' option", + "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/view-or-configure-the-backup-compression-default-server-configuration-option", + "level": "Information", + "tags": [ + "DefaultRuleset", + "Configuration", + "Performance", + "Backup" + ], + "condition": "@backup_compression", + "probes": [ + "SysConfiguration" + ] + }, { "id": "BackupTables", "itemType": "definition", @@ -9283,7 +9873,7 @@ "itemType": "definition", "target": { "type": "Server", - "engineEdition": "SqlServer, ManagedInstance", + "engineEdition": "Enterprise, ManagedInstance", "version": "[11.0,)", "platform": [ "Windows", @@ -9484,7 +10074,7 @@ }, "displayName": "Uncompressed database tables and indexes", "description": "The compression capability at either the row or page level provides an opportunity to save disk space and improve performance, with the tradeoff of requiring a bit more CPU to compress and decompress the data, but requiring less memory and disk access improving performance in many workloads. The data pages are kept compressed when they are uploaded to memory. This check fires if a relatively large amount of space is on indexes without compression (for example, more than 10GB).", - "message": "Compress index: @{IndexName}, total space: @{TotalSpaceMB:N2} MB", + "message": "Turn on compression for these @{ObjectType}: @{ObjectName}, total space used by these objects: @{TotalSpaceMB:N2} MB", "helpLink": "https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide", "level": "Information", "tags": [ @@ -9492,6 +10082,7 @@ "Configuration", "Performance" ], + "topObjectsForCompression": 10, "threshold": 1280000, "condition": { "lt": [ @@ -9509,8 +10100,27 @@ { "id": "TopUncompressedTables", "params": { - "topN": 10 - } + "topN": "@topObjectsForCompression" + }, + "transform": [ + { + "type": "aggregate", + "group": "ObjectType", + "map": { + "ObjectName": "join", + "TotalIndexPages": "sum" + } + }, + { + "type": "toString", + "map": { + "ObjectType": { + "tables": 0, + "indexes": 1 + } + } + } + ] } ], "locals": { @@ -9676,12 +10286,87 @@ "DatabaseConfiguration" ] }, + { + "id": "DbState", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "displayName": "Database with unavailable state", + "description": "Database unavailability may affect expected application behavior due to the impossibility of establishing user connections. The issue occurs when a database is in any of the following states: 'RECOVERY_PENDING', 'RECOVERING', 'SUSPECT', or 'RESTORING'.", + "message": "Check '@{DbName}' database availability. Current database state is: @{DbStateDesc}", + "helpLink": "https://docs.microsoft.com/sql/relational-databases/databases/database-states", + "level": "Low", + "tags": [ + "DefaultRuleset", + "Configuration" + ], + "condition": { + "or": [ + { + "ne": [ + "@source_database_id", + null + ] + }, + { + "not": { + "in": [ + "@DbState", + "@unavailableStates" + ] + } + } + ] + }, + "unavailableStates": [ + 1, + 2, + 3, + 4 + ], + "probes": [ + "DatabasesState" + ] + }, + { + "id": "DisallowResultsTriggers", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "platform": [ + "Windows", + "Linux" + ], + "version": "[11.0,)" + }, + "tags": [ + "DefaultRuleset", + "Configuration" + ], + "displayName": "Option 'disallow results from triggers' is disabled", + "description": "Use the 'disallow results from triggers' option to control whether triggers return result sets. Triggers that return result sets may cause unexpected behavior in applications that are not designed to work with them.", + "message": "Enable 'disallow results from triggers' option as the ability to return result sets from triggers will be removed in a future version", + "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/disallow-results-from-triggers-server-configuration-option", + "level": "Information", + "condition": "@disallow_results_from_triggers", + "probes": [ + "SysConfiguration" + ] + }, { "id": "EKMProvider", "itemType": "definition", "target": { "type": "Server", - "engineEdition": "Enterprise, ManagedInstance", + "engineEdition": "Standard, Enterprise, ManagedInstance", "version": "[11.0,)", "platform": [ "Windows", @@ -9704,6 +10389,96 @@ "SysConfiguration" ] }, + { + "id": "EKMProvider", + "itemType": "override", + "targetFilter": { + "engineEdition": "Standard", + "version": "[11.0, 15.0)" + }, + "enabled": false + }, + { + "id": "FileMaxSize", + "itemType": "definition", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "displayName": "Setting 'Autogrow' for data files", + "description": "This check verifies the 'autogrow' settings of data files for all system and user databases. In SQL Server, a log file specified with unlimited growth has a maximum size of 2 TB, and a data file has a maximum size of 16 TB. There is no maximum size when this option is specified for a FILESTREAM container. It continues to grow until the disk is full. If there is no space available, performance issues may occur and the database may become unavailable.", + "message": "Check 'autogrow' setting. Currently maximum size of @{maxsize_in_mb} MBs is set for @{type_desc} file @{fileName} in database @{databaseName}", + "helpLink": "https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-file-and-filegroup-options", + "level": "Information", + "tags": [ + "DefaultRuleset", + "Performance", + "DBFileConfiguration" + ], + "defaultLogValues": [ + -1, + 0, + 268435456 + ], + "condition": { + "and": [ + { + "or": [ + { + "ne": [ + "@type", + 0 + ] + }, + { + "le": [ + "@max_size", + 0 + ] + } + ] + }, + { + "or": [ + { + "ne": [ + "@type", + 1 + ] + }, + { + "in": [ + "@max_size", + "@defaultLogValues" + ] + } + ] + } + ] + }, + "probes": [ + { + "id": "DatabaseMasterFiles", + "params": { + "type": null, + "dbId": null + } + } + ], + "locals": { + "maxsize_in_mb": { + "div": [ + "@max_size", + 128 + ] + } + } + }, { "id": "FilestreamAccessLevel", "itemType": "definition", @@ -9891,6 +10666,53 @@ "SysConfiguration" ] }, + { + "id": "FullTextDefaultLang", + "itemType": "definition", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)", + "platform": [ + "Windows", + "Linux" + ] + }, + "tags": [ + "DefaultRuleset", + "Configuration" + ], + "displayName": "Not supported value for 'default full-text language' option", + "description": "The value of the 'default full-text language' option is used in a full-text index when no language is specified. If the default full-text language is not supported or the linguistic analysis package is not available, CREATE FULLTEXT INDEX and ALTER FULLTEXT INDEX statements will fail.", + "message": "Set 'default full-text language' option to a supported value", + "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/configure-the-default-full-text-language-server-configuration-option", + "condition": { + "or": [ + { + "not": "@IsFulltextInstalled" + }, + { + "in": [ + "@default_full_text_language", + "@lcid" + ] + } + ] + }, + "probes": [ + "SysConfiguration", + { + "id": "SysFullTextLanguages", + "transform": { + "type": "aggregate", + "map": { + "lcid": "array" + } + } + }, + "FullTextServiceInfo" + ] + }, { "id": "FullTextNoiseWords", "itemType": "definition", @@ -9933,7 +10755,7 @@ }, "displayName": "Non-default value for 'PH timeout' option", "description": "The 'PH timeout' option controls the number of seconds that the full-text protocol handler will wait to connect to a database before reaching the timeout threshold. You can increase the 'PH timeout' value when connection attempts are timing out due to temporary network issues.", - "message": "Set 'PH timeout' option to default", + "message": "Review non-default value @{PH_timeout} for the 'PH timeout' option", "helpLink": "https://docs.microsoft.com/sql/database-engine/configure-windows/ph-timeout-server-configuration-option", "level": "Information", "tags": [ @@ -9990,7 +10812,8 @@ "engineEdition": "SqlServer", "version": [ "[11.0.7001,12.0)", - "[12.0.5000, )" + "[12.0.6024,13.0)", + "[13.0.4001,)" ] }, "tags": [ @@ -10266,6 +11089,51 @@ "DatabaseConfiguration" ] }, + { + "id": "MoreIndexesThanCols", + "itemType": "definition", + "target": { + "type": "Database", + "platform": [ + "Windows", + "Linux" + ], + "name": { + "not": [ + "master", + "model", + "msdb", + "tempdb" + ] + }, + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)" + }, + "tags": [ + "DefaultRuleset", + "Performance", + "Indexes" + ], + "displayName": "Tables with more indexes than columns", + "description": "One or more database tables have been identified as having more indexes than columns. During inserts, updates and deletes, every index on a table has to be evaluated and, potentially, updated. If too many indexes exist, SQL Server will spend unnecessary resources maintaining indexes that may not be used. This can significantly affect the amount of disk I/O generated and, subsequently, performance.", + "message": "Consider removing potentially unnecessary indexes on table @{SchemaName}.@{TableName} that has more indexes than columns", + "helpLink": "https://docs.microsoft.com/sql/relational-databases/sql-server-index-design-guide", + "level": "Information", + "condition": { + "le": [ + { + "sub": [ + "@IndexCount", + "@FilteredIndexCount" + ] + }, + "@ColumnCount" + ] + }, + "probes": [ + "TablesInformation" + ] + }, { "id": "OneDbPerPool", "itemType": "definition", @@ -10383,7 +11251,8 @@ "ccmsqlce.dll", "msdasql.dll", "odbccp32.dll", - "umpdc.dll" + "umpdc.dll", + "sqlevn70.rll" ], "condition": { "or": [ @@ -10720,6 +11589,50 @@ } ] }, + { + "id": "TempDbSameVolume", + "itemType": "definition", + "target": { + "type": "Database", + "name": "tempdb", + "platform": "Windows", + "engineEdition": "SqlServer", + "version": "[11.0,)", + "machineType": { + "not": "AzureVm" + } + }, + "tags": [ + "DefaultRuleset", + "Performance", + "DBFileConfiguration" + ], + "displayName": "Tempdb and user databases should not share volumes", + "description": "The tempdb system database is used for temporary objects, internal objects and row versions. Tempdb is often heavily used when queries are executed and, if it has files placed on the same volume as user database files, there can be contention for the IO resources.", + "message": "Place tempdb on a separate volume. Tempdb and user databases share volume @{volume_mount_point}", + "helpLink": "https://docs.microsoft.com/sql/relational-databases/databases/tempdb-database", + "level": "Medium", + "probes": [ + { + "id": "DatabaseSharedVolumes", + "params": { + "is_system_database": 0 + }, + "transform": [ + { + "type": "aggregate", + "group": "volume_mount_point" + }, + { + "type": "aggregate", + "map": { + "volume_mount_point": "join" + } + } + ] + } + ] + }, { "id": "TwoDigitYearCutoff", "itemType": "definition", @@ -10876,7 +11789,7 @@ ] }, "implementation": { - "query": "SELECT COUNT(id) AS [BlackBoxTraceCount] FROM [sys].[traces] WHERE [path] LIKE '%blackbox%.trc' AND status=1;" + "query": "SELECT COUNT(id) AS [BlackBoxTraceCount] FROM [sys].[traces] WITH (NOLOCK) WHERE [path] LIKE '%blackbox%.trc' AND status = 1;" } } ], @@ -10894,7 +11807,7 @@ ] }, "implementation": { - "query": "SELECT COUNT(id) AS [DefaultTraceCount] FROM [sys].[traces] WHERE is_default = 1 AND status = 1;" + "query": "SELECT COUNT(id) AS [DefaultTraceCount] FROM [sys].[traces] WITH (NOLOCK) WHERE is_default = 1 AND status = 1;" } } ], @@ -11006,13 +11919,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT QUOTENAME(fk.parent_schema_name)+ '.' + QUOTENAME(fk.parent_table_name) + '.' + QUOTENAME(fk.constraint_name) AS ConstraintName FROM ( SELECT t.name AS [parent_schema_name], OBJECT_NAME(FKC.parent_object_id) [parent_table_name], OBJECT_NAME(constraint_object_id) AS [constraint_name], SUBSTRING((SELECT ',' + RTRIM(COL_NAME(k.parent_object_id,parent_column_id)) AS [data()] FROM sys.foreign_key_columns k (NOLOCK) INNER JOIN sys.foreign_keys (NOLOCK) ON k.constraint_object_id = [object_id] AND k.constraint_object_id = FKC.constraint_object_id ORDER BY constraint_column_id FOR XML PATH('')), 2, 8000) AS [parent_columns] FROM sys.foreign_key_columns FKC (NOLOCK) INNER JOIN sys.objects o (NOLOCK) ON FKC.parent_object_id = o.[object_id] INNER JOIN sys.tables mst (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas t (NOLOCK) ON t.[schema_id] = mst.[schema_id] INNER JOIN sys.objects so (NOLOCK) ON FKC.referenced_object_id = so.[object_id] WHERE o.type = 'U' AND so.type = 'U' AND o.is_ms_shipped = 0 GROUP BY o.[schema_id],so.[schema_id],FKC.parent_object_id,constraint_object_id,referenced_object_id,t.name ) fk WHERE NOT EXISTS (SELECT 1 FROM ( SELECT t.name AS schemaName, OBJECT_NAME(mst.[object_id]) AS objectName, SUBSTRING(( SELECT ',' + RTRIM(ac.name) FROM sys.tables AS st INNER JOIN sys.indexes AS mi ON st.[object_id] = mi.[object_id] INNER JOIN sys.index_columns AS ic ON mi.[object_id] = ic.[object_id] AND mi.[index_id] = ic.[index_id] INNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] WHERE i.[object_id] = mi.[object_id] AND i.index_id = mi.index_id AND ic.is_included_column = 0 ORDER BY ac.column_id FOR XML PATH('')), 2, 8000) AS KeyCols FROM sys.indexes AS i INNER JOIN sys.tables AS mst ON mst.[object_id] = i.[object_id] INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id] WHERE i.[type] IN (1,2,5,6) AND i.is_unique_constraint = 0 AND mst.is_ms_shipped = 0 ) ict WHERE fk.parent_schema_name = ict.schemaName AND fk.parent_table_name = ict.objectName AND REPLACE(fk.parent_columns,' ,',',') = ict.KeyCols);", - "transform": { - "type": "aggregate", - "map": { - "ConstraintName": "join" - } - } + "query": "SELECT QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id)) AS TableName FROM ( SELECT FKC.parent_object_id, constraint_object_id, REPLACE(SUBSTRING((SELECT ',' + RTRIM(COL_NAME(k.parent_object_id,parent_column_id)) FROM sys.foreign_key_columns k (NOLOCK) INNER JOIN sys.foreign_keys (NOLOCK) ON k.constraint_object_id = [object_id] AND k.constraint_object_id = FKC.constraint_object_id ORDER BY constraint_column_id FOR XML PATH('')), 2, 8000), ' ,',',') AS [parent_columns] FROM sys.foreign_key_columns FKC (NOLOCK) INNER JOIN sys.objects o (NOLOCK) ON FKC.parent_object_id = o.[object_id] INNER JOIN sys.objects so (NOLOCK) ON FKC.referenced_object_id = so.[object_id] WHERE o.type = 'U' AND so.type = 'U' AND o.is_ms_shipped = 0 GROUP BY o.[schema_id],so.[schema_id],FKC.parent_object_id,constraint_object_id,referenced_object_id ) AS Const LEFT JOIN ( SELECT mst.[object_id], REPLACE(SUBSTRING(( SELECT ',' + RTRIM(ac.name) FROM sys.tables AS st (NOLOCK) INNER JOIN sys.indexes AS mi (NOLOCK) ON st.[object_id] = mi.[object_id] INNER JOIN sys.index_columns AS ic (NOLOCK) ON mi.[object_id] = ic.[object_id] AND mi.[index_id] = ic.[index_id] INNER JOIN sys.all_columns AS ac (NOLOCK) ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] WHERE i.[object_id] = mi.[object_id] AND i.index_id = mi.index_id AND ic.is_included_column = 0 ORDER BY ac.column_id FOR XML PATH('')), 2, 8000), ' ,',',') AS KeyCols FROM sys.indexes AS i (NOLOCK) INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = i.[object_id] WHERE i.[type] IN (1,2,5,6) AND i.is_unique_constraint = 0 AND mst.is_ms_shipped = 0 ) AS IdxConst ON Const.parent_object_id = IdxConst.[object_id] AND Const.parent_columns = IdxConst.KeyCols WHERE IdxConst.[object_id] IS NULL GROUP BY parent_object_id" } } ], @@ -11047,7 +11954,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT ss.name AS [Schema_Name], so.name AS [Object_Name], so.type_desc, CASE WHEN sm.[definition] LIKE '%FORCE ORDER%' THEN '[FORCE ORDER Hint]' WHEN sm.[definition] LIKE '%MERGE JOIN%' OR sm.[definition] LIKE '%LOOP JOIN%' OR sm.[definition] LIKE '%HASH JOIN%' THEN '[JOIN Hint]' END AS Hint FROM [sys].[sql_modules] AS sm INNER JOIN [sys].[objects] AS so ON sm.[object_id] = so.[object_id] INNER JOIN [sys].[schemas] AS ss ON so.[schema_id] = ss.[schema_id] WHERE (sm.[definition] LIKE '%FORCE ORDER%' OR sm.[definition] LIKE '%MERGE JOIN%' OR sm.[definition] LIKE '%LOOP JOIN%' OR sm.[definition] LIKE '%HASH JOIN%') AND OBJECTPROPERTY(sm.[object_id],'IsMSShipped') = 0;" + "query": "SELECT ss.name AS [Schema_Name], so.name AS [Object_Name], so.type_desc, CASE WHEN sm.[definition] LIKE '%FORCE ORDER%' THEN '[FORCE ORDER Hint]' WHEN sm.[definition] LIKE '%MERGE JOIN%' OR sm.[definition] LIKE '%LOOP JOIN%' OR sm.[definition] LIKE '%HASH JOIN%' THEN '[JOIN Hint]' END AS Hint FROM [sys].[sql_modules] AS sm WITH (NOLOCK) INNER JOIN [sys].[objects] AS so WITH (NOLOCK) ON sm.[object_id] = so.[object_id] INNER JOIN [sys].[schemas] AS ss WITH (NOLOCK) ON so.[schema_id] = ss.[schema_id] WHERE ( sm.[definition] LIKE '%FORCE ORDER%' OR sm.[definition] LIKE '%MERGE JOIN%' OR sm.[definition] LIKE '%LOOP JOIN%' OR sm.[definition] LIKE '%HASH JOIN%' ) AND OBJECTPROPERTY(sm.[object_id], 'IsMSShipped') = 0;" } } ], @@ -11082,7 +11989,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT QUOTENAME(t.name) AS [Schema], QUOTENAME(o.[name]) AS [Object], i.name AS [IndexName] FROM [sys].[indexes] i INNER JOIN [sys].[objects] AS o ON o.[object_id] = i.[object_id] INNER JOIN [sys].[tables] AS mst ON mst.[object_id] = i.[object_id] INNER JOIN [sys].[schemas] AS t ON t.[schema_id] = mst.[schema_id] WHERE i.is_hypothetical = 1 and o.is_ms_shipped = 0;" + "query": "SELECT QUOTENAME(t.name) AS [Schema], QUOTENAME(o.[name]) AS [Object], i.name AS [IndexName] FROM [sys].[indexes] AS i WITH (NOLOCK) INNER JOIN [sys].[objects] AS o WITH (NOLOCK) ON o.[object_id] = i.[object_id] INNER JOIN [sys].[tables] AS mst WITH (NOLOCK) ON mst.[object_id] = i.[object_id] INNER JOIN [sys].[schemas] AS t WITH (NOLOCK) ON t.[schema_id] = mst.[schema_id] WHERE i.is_hypothetical = 1 and o.is_ms_shipped = 0;" } } ], @@ -11100,7 +12007,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT QUOTENAME(t.name) AS [Schema], QUOTENAME(o.[name]) AS [Object], s.name AS [StatName] FROM [sys].[stats] s INNER JOIN [sys].[objects] AS o (NOLOCK) ON o.[object_id] = s.[object_id] INNER JOIN [sys].[tables] AS mst (NOLOCK) ON mst.[object_id] = s.[object_id] INNER JOIN [sys].[schemas] AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id] WHERE (s.name LIKE 'hind_%' OR s.name LIKE '_dta_stat%') AND auto_created = 0 AND s.name NOT IN (SELECT name FROM sys.indexes) AND o.[is_ms_shipped] = 0;" + "query": "SELECT QUOTENAME(t.name) AS [Schema], QUOTENAME(o.[name]) AS [Object], s.name AS [StatName] FROM [sys].[stats] AS s WITH (NOLOCK) INNER JOIN [sys].[objects] AS o (NOLOCK) ON o.[object_id] = s.[object_id] INNER JOIN [sys].[tables] AS mst (NOLOCK) ON mst.[object_id] = s.[object_id] INNER JOIN [sys].[schemas] AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id] WHERE ( s.name LIKE 'hind_%' OR s.name LIKE '_dta_stat%' ) AND auto_created = 0 AND s.name NOT IN ( SELECT name FROM sys.indexes ) AND o.[is_ms_shipped] = 0;" } } ], @@ -11128,7 +12035,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT RIGHT(i.[statement],LEN(i.[statement])-(LEN(m.[name])+3)) AS [Table], CASE WHEN (i.equality_columns IS NOT NULL AND i.inequality_columns IS NULL) THEN i.equality_columns WHEN (i.equality_columns IS NULL AND i.inequality_columns IS NOT NULL) THEN i.inequality_columns ELSE i.equality_columns+','+i.inequality_columns END AS [KeyCols], ISNULL(i.included_columns,'') AS [IncludedCols], (CONVERT(NUMERIC(19,3),s.user_seeks)+CONVERT(NUMERIC(19,3),s.user_scans))*CONVERT(NUMERIC(19,3),s.avg_total_user_cost)*CONVERT(NUMERIC(19,3),s.avg_user_impact) AS [Score] FROM [sys].[dm_db_missing_index_details] i INNER JOIN [master].[sys].[databases] m ON i.database_id=m.database_id INNER JOIN [sys].[dm_db_missing_index_groups] g ON i.index_handle=g.index_handle INNER JOIN [sys].[dm_db_missing_index_group_stats] s ON s.group_handle=g.index_group_handle WHERE m.[name]=@TargetName AND OBJECTPROPERTY(i.[object_id], 'IsMSShipped') = 0" + "query": "SELECT RIGHT( i.[statement], LEN(i.[statement]) -(LEN(m.[name]) + 3) ) AS [Table], CASE WHEN ( i.equality_columns IS NOT NULL AND i.inequality_columns IS NULL ) THEN i.equality_columns WHEN ( i.equality_columns IS NULL AND i.inequality_columns IS NOT NULL ) THEN i.inequality_columns ELSE i.equality_columns + ',' + i.inequality_columns END AS [KeyCols], ISNULL(i.included_columns, '') AS [IncludedCols], ( CONVERT(NUMERIC(19, 3), s.user_seeks) + CONVERT(NUMERIC(19, 3), s.user_scans) ) * CONVERT(NUMERIC(19, 3), s.avg_total_user_cost) * CONVERT(NUMERIC(19, 3), s.avg_user_impact) AS [Score] FROM [sys].[dm_db_missing_index_details] i INNER JOIN [master].[sys].[databases] AS m WITH (NOLOCK) ON i.database_id = m.database_id INNER JOIN [sys].[dm_db_missing_index_groups] g ON i.index_handle = g.index_handle INNER JOIN [sys].[dm_db_missing_index_group_stats] s ON s.group_handle = g.index_group_handle WHERE m.[name] = @TargetName AND OBJECTPROPERTY(i.[object_id], 'IsMSShipped') = 0" } } ], @@ -11145,7 +12052,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT db.recovery_model, db.recovery_model_desc, fb.LastFullBackup, tl.LastTLBackup FROM [master].[sys].[databases] db (NOLOCK) LEFT JOIN (SELECT b.database_name, DATEDIFF(HH, MAX(b.backup_finish_date),GETDATE()) AS LastFullBackup FROM [msdb].[dbo].[backupset] b WHERE b.is_copy_only=0 AND b.type='D' GROUP BY b.database_name) fb ON fb.database_name=db.name LEFT JOIN (SELECT b.database_name, DATEDIFF(HH, MAX(b.backup_finish_date), GETDATE()) AS LastTLBackup FROM [msdb].[dbo].[backupset] b WHERE b.is_copy_only=0 AND b.type='L' GROUP BY b.database_name HAVING MAX(b.backup_finish_date)>=(SELECT MAX(f.backup_finish_date) FROM [msdb].[dbo].[backupset] f WHERE f.is_copy_only=0 AND f.type IN ('D','I') AND f.database_name=b.database_name GROUP BY f.database_name )) tl ON fb.database_name=tl.database_name WHERE db.name=@TargetName;" + "query": "SELECT db.recovery_model, db.recovery_model_desc, fb.LastFullBackup, tl.LastTLBackup FROM [master].[sys].[databases] AS db WITH (NOLOCK) LEFT JOIN ( SELECT b.database_name, DATEDIFF(HH, MAX(b.backup_finish_date), GETDATE()) AS LastFullBackup FROM [msdb].[dbo].[backupset] AS b WITH (NOLOCK) WHERE b.is_copy_only = 0 AND b.type = 'D' GROUP BY b.database_name ) fb ON fb.database_name = db.name LEFT JOIN ( SELECT b.database_name, DATEDIFF(HH, MAX(b.backup_finish_date), GETDATE()) AS LastTLBackup FROM [msdb].[dbo].[backupset] AS b WITH (NOLOCK) WHERE b.is_copy_only = 0 AND b.type = 'L' GROUP BY b.database_name HAVING MAX(b.backup_finish_date) >=( SELECT MAX(f.backup_finish_date) FROM [msdb].[dbo].[backupset] AS f WITH (NOLOCK) WHERE f.is_copy_only = 0 AND f.type IN ('D', 'I') AND f.database_name = b.database_name GROUP BY f.database_name ) ) tl ON fb.database_name = tl.database_name WHERE db.name = @TargetName;" } } ], @@ -11162,7 +12069,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT COUNT(DISTINCT size) AS filesizeCount FROM tempdb.sys.database_files WHERE [type] = 0" + "query": "SELECT COUNT(DISTINCT size) AS filesizeCount FROM tempdb.sys.database_files WITH (NOLOCK) WHERE [type] = 0" } } ], @@ -11196,7 +12103,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT mf.database_id, dbs.name AS databaseName, [type], [type_desc], physical_name, mf.name AS fileName, size, growth, is_percent_growth, mf.max_size, volume_mount_point, volume_id FROM [sys].[master_files] AS mf INNER JOIN [sys].databases AS dbs ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE mf.database_id = ISNULL(@dbId, mf.database_id) AND [type] = ISNULL(@type, [type])" + "query": "SELECT mf.database_id, dbs.name AS databaseName, [type], [type_desc], physical_name, mf.name AS fileName, size, growth, is_percent_growth, mf.max_size, volume_mount_point, volume_id FROM [sys].[master_files] AS mf WITH (NOLOCK) INNER JOIN [sys].databases AS dbs WITH (NOLOCK) ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE mf.database_id = ISNULL(@dbId, mf.database_id) AND [type] = ISNULL(@type, [type])" } }, { @@ -11212,7 +12119,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT df.[type], physical_name, df.name AS fileName, size, growth, is_percent_growth, ISNULL(FILEPROPERTY(df.name, 'SpaceUsed'), 0) AS spaceUsed, volume_mount_point, volume_id FROM [sys].[database_files] AS df CROSS APPLY sys.dm_os_volume_stats(DB_ID(), df.file_id) WHERE df.[type] = ISNULL(@type, df.[type]) AND is_percent_growth = ISNULL(@is_percent_growth, is_percent_growth)" + "query": "SELECT df.[type], physical_name, df.name AS fileName, size, growth, is_percent_growth, ISNULL(FILEPROPERTY(df.name, 'SpaceUsed'), 0) AS spaceUsed, volume_mount_point, volume_id FROM [sys].[database_files] AS df WITH (NOLOCK) CROSS APPLY sys.dm_os_volume_stats(DB_ID(), df.file_id) WHERE df.[type] = ISNULL(@type, df.[type]) AND is_percent_growth = ISNULL(@is_percent_growth, is_percent_growth)" } } ], @@ -11223,7 +12130,8 @@ "type": "Server", "version": [ "[11.0.7001,12.0)", - "[12.0.5000,)" + "[12.0.6024,13.0)", + "[13.0.4001,)" ], "platform": [ "Windows", @@ -11265,7 +12173,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT i.object_id, QUOTENAME(t.name) + '.' + QUOTENAME(st.name) AS TableName, QUOTENAME(i.name) AS IndexName, QUOTENAME(ac.Name) AS ColumnName, ic.is_included_column, i.is_primary_key, i.filter_definition, i.is_unique, ic.key_ordinal, sty.name AS ColTypeName, CASE sty.name WHEN 'nvarchar' THEN ac.max_length / 2 ELSE ac.max_length END AS ColTypeSize, i.fill_factor, i.is_disabled, i.type AS IndexType, index_stat.Hits, index_stat.Reads_Ratio, index_stat.last_user_update FROM [sys].[tables] AS st INNER JOIN [sys].[schemas] AS t ON t.[schema_id] = st.[schema_id] INNER JOIN [sys].[indexes] AS i ON st.[object_id] = i.[object_id] INNER JOIN [sys].[index_columns] AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] INNER JOIN [sys].[all_columns] AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] INNER JOIN [sys].[types] AS sty ON ac.user_type_id = sty.user_type_id LEFT JOIN( SELECT s.object_id, s.index_id, ( stat.user_seeks + stat.user_scans + stat.user_lookups ) AS [Hits], RTRIM( CONVERT( NVARCHAR(10), CAST( CASE WHEN ( stat.user_seeks + stat.user_scans + stat.user_lookups ) = 0 THEN 0 ELSE CONVERT( REAL, ( stat.user_seeks + stat.user_scans + stat.user_lookups ) ) * 100 /CASE ( stat.user_seeks + stat.user_scans + stat.user_lookups + stat.user_updates ) WHEN 0 THEN 1 ELSE CONVERT( REAL, ( stat.user_seeks + stat.user_scans + stat.user_lookups + stat.user_updates ) ) END END AS DECIMAL(18, 2) ) ) ) AS [Reads_Ratio], MAX(stat.last_user_update) AS last_user_update FROM sys.indexes s INNER JOIN sys.dm_db_index_usage_stats stat on stat.object_id = s.object_id and stat.index_id = s.index_id WHERE s.type IN (2, 6) AND s.is_primary_key = 0 AND s.is_unique_constraint = 0 GROUP BY s.object_id, s.index_id, stat.user_seeks, stat.user_scans, stat.user_lookups, stat.user_updates ) index_stat ON index_stat.object_id = i.object_id AND index_stat.index_id = i.index_id WHERE i.type IN (1, 2, 5, 6) AND st.is_ms_shipped = 0 AND i.is_unique_constraint = 0", + "query": "SELECT i.object_id, QUOTENAME(t.name) + '.' + QUOTENAME(st.name) AS TableName, QUOTENAME(i.name) AS IndexName, QUOTENAME(ac.Name) AS ColumnName, ic.is_included_column, i.is_primary_key, i.filter_definition, i.is_unique, ic.key_ordinal, CASE sty.name WHEN 'nvarchar' THEN ac.max_length / 2 ELSE ac.max_length END AS ColTypeSize, i.fill_factor, i.is_disabled, i.type AS IndexType, ISNULL(index_stat.Hits, 0) AS [Hits], ISNULL(index_stat.Reads_Ratio, 0) AS Reads_Ratio FROM [sys].[tables] AS st WITH (NOLOCK) INNER JOIN [sys].[schemas] AS t WITH (NOLOCK) ON t.[schema_id] = st.[schema_id] INNER JOIN [sys].[indexes] AS i WITH (NOLOCK) ON st.[object_id] = i.[object_id] INNER JOIN [sys].[index_columns] AS ic WITH (NOLOCK) ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] INNER JOIN [sys].[all_columns] AS ac WITH (NOLOCK) ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] INNER JOIN [sys].[types] AS sty WITH (NOLOCK) ON ac.user_type_id = sty.user_type_id LEFT JOIN( SELECT s.object_id, s.index_id, ( stat.user_seeks + stat.user_scans + stat.user_lookups ) AS [Hits], CAST( CASE WHEN ( stat.user_seeks + stat.user_scans + stat.user_lookups ) = 0 THEN 0 ELSE CONVERT( REAL, ( stat.user_seeks + stat.user_scans + stat.user_lookups ) ) * 100 /CASE ( stat.user_seeks + stat.user_scans + stat.user_lookups + stat.user_updates ) WHEN 0 THEN 1 ELSE CONVERT( REAL, ( stat.user_seeks + stat.user_scans + stat.user_lookups + stat.user_updates ) ) END END AS DECIMAL(18, 2) ) AS [Reads_Ratio] FROM sys.indexes AS s WITH (NOLOCK) INNER JOIN sys.dm_db_index_usage_stats stat on stat.object_id = s.object_id and stat.index_id = s.index_id WHERE s.type IN (2, 6) AND s.is_primary_key = 0 AND s.is_unique_constraint = 0 GROUP BY s.object_id, s.index_id, stat.user_seeks, stat.user_scans, stat.user_lookups, stat.user_updates ) index_stat ON index_stat.object_id = i.object_id AND index_stat.index_id = i.index_id WHERE i.type IN (1, 2, 5, 6) AND st.is_ms_shipped = 0 AND i.is_unique_constraint = 0", "transform": { "type": "indexDefinition" } @@ -11281,7 +12189,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT sao.name AS [Object_Name] FROM master.sys.all_objects sao INNER JOIN master.sys.schemas ss ON sao.[schema_id] = ss.[schema_id] WHERE sao.is_ms_shipped = 0 AND sao.[type] IN ('AF','FN','P','IF','PC','TF','TR','T','V') ORDER BY sao.name, sao.type_desc;", + "query": "SELECT sao.name AS [Object_Name] FROM master.sys.all_objects AS sao WITH (NOLOCK) INNER JOIN master.sys.schemas AS ss WITH (NOLOCK) ON sao.[schema_id] = ss.[schema_id] WHERE sao.is_ms_shipped = 0 AND sao.[type] IN ('AF', 'FN', 'P', 'IF', 'PC', 'TF', 'TR', 'T', 'V') ORDER BY sao.name, sao.type_desc;", "transform": { "type": "aggregate", "map": { @@ -11344,7 +12252,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "DECLARE @cmd NVARCHAR(max) = N''; SELECT @cmd = @cmd + N' USE ' + QUOTENAME([name]) + N'; SELECT msa.publisher_db ,msa.publication FROM dbo.MSdistribution_history AS msh INNER JOIN dbo.MSrepl_errors AS mse ON mse.id = msh.error_id INNER JOIN dbo.MSdistribution_agents AS msa ON msh.agent_id = msa.id WHERE mse.time >= DATEADD(hh, - 24, GETDATE()) GROUP BY msa.publisher_db ,msa.publication;' FROM [master].sys.databases WHERE is_distributor = 1; EXEC (@cmd);" + "query": "DECLARE @cmd NVARCHAR(max) = N''; SELECT @cmd = @cmd + N' USE ' + QUOTENAME([name]) + N'; SELECT msa.publisher_db ,msa.publication FROM dbo.MSdistribution_history AS msh WITH (NOLOCK) INNER JOIN dbo.MSrepl_errors AS mse WITH (NOLOCK) ON mse.id = msh.error_id INNER JOIN dbo.MSdistribution_agents AS msa WITH (NOLOCK) ON msh.agent_id = msa.id WHERE mse.time >= DATEADD(hh, - 24, GETDATE()) GROUP BY msa.publisher_db ,msa.publication;' FROM [master].sys.databases WITH (NOLOCK) WHERE is_distributor = 1; EXEC (@cmd);" } } ], @@ -11362,7 +12270,7 @@ ] }, "implementation": { - "query": "SELECT DISTINCT severity, message_id FROM [msdb].[dbo].[sysalerts]", + "query": "SELECT DISTINCT severity, message_id FROM [msdb].[dbo].[sysalerts] WITH (NOLOCK)", "transform": { "type": "aggregate", "map": { @@ -11386,7 +12294,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "DECLARE @word TABLE (word NVARCHAR(50)); INSERT INTO @word VALUES ('0') ,('012') ,('0123') ,('01234') ,('012345') ,('0123456') ,('01234567') ,('012345678') ,('0123456789') ,('01234567890') ,('11111') ,('111111') ,('1111111') ,('11111111') ,('21') ,('321') ,('4321') ,('54321') ,('654321') ,('7654321') ,('87654321') ,('987654321') ,('0987654321') ,('pwd') ,('Password') ,('password') ,('P@ssw0rd') ,('p@ssw0rd') ,('Teste') ,('teste') ,('Test') ,('test') ,('') ,('p@wd') ,('Qwerty') ,('qwerty') ,('Password1') ,('password1'); SELECT RTRIM(s.[name]) AS [PasswordData] FROM @word d INNER JOIN [master].sys.sql_logins s ON PWDCOMPARE(d.word, s.[password_hash]) = 1 UNION SELECT RTRIM(s.[name]) AS [PasswordData] FROM [master].sys.sql_logins s WHERE PWDCOMPARE(RTRIM(RTRIM(s.[name])), s.[password_hash]) = 1 UNION SELECT RTRIM(s.[name]) AS [PasswordData] FROM [master].sys.sql_logins s WHERE s.[password_hash] IS NULL AND s.[name] NOT IN ( 'MSCRMSqlClrLogin' ,'##MS_SmoExtendedSigningCertificate##' ,'##MS_PolicySigningCertificate##' ,'##MS_SQLResourceSigningCertificate##' ,'##MS_SQLReplicationSigningCertificate##' ,'##MS_SQLAuthenticatorCertificate##' ,'##MS_AgentSigningCertificate##' ,'##MS_SQLEnableSystemAssemblyLoadingUser##' )", + "query": "DECLARE @word TABLE (word NVARCHAR(50)); INSERT INTO @word VALUES ('0') ,('012') ,('0123') ,('01234') ,('012345') ,('0123456') ,('01234567') ,('012345678') ,('0123456789') ,('01234567890') ,('11111') ,('111111') ,('1111111') ,('11111111') ,('21') ,('321') ,('4321') ,('54321') ,('654321') ,('7654321') ,('87654321') ,('987654321') ,('0987654321') ,('pwd') ,('Password') ,('password') ,('P@ssw0rd') ,('p@ssw0rd') ,('Teste') ,('teste') ,('Test') ,('test') ,('') ,('p@wd') ,('Qwerty') ,('qwerty') ,('Password1') ,('password1'); SELECT RTRIM(s.[name]) AS [PasswordData] FROM [master].sys.sql_logins AS s WITH (NOLOCK) LEFT JOIN @word AS d ON PWDCOMPARE(d.word, s.[password_hash]) = 1 WHERE ( d.word IS NOT NULL OR PWDCOMPARE(RTRIM(RTRIM(s.[name])), s.[password_hash]) = 1 OR ( ( s.[password_hash] IS NULL OR s.[is_policy_checked] = 0 OR s.[is_expiration_checked] = 0 ) AND s.[name] NOT IN ( 'MSCRMSqlClrLogin' ,'##MS_SmoExtendedSigningCertificate##' ,'##MS_PolicyEventProcessingLogin##' ,'##MS_PolicySigningCertificate##' ,'##MS_PolicyTsqlExecutionLogin##' ,'##MS_SQLResourceSigningCertificate##' ,'##MS_SQLReplicationSigningCertificate##' ,'##MS_SQLAuthenticatorCertificate##' ,'##MS_AgentSigningCertificate##' ,'##MS_SQLEnableSystemAssemblyLoadingUser##' ) ) ) AND s.is_disabled = ISNULL(@is_disabled, s.is_disabled)", "transform": { "type": "aggregate", "map": { @@ -11424,7 +12332,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT s.[name]+'.'+so.[name] AS ObjectName FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] = 'P' AND so.[name] LIKE 'sp[_]%' AND so.[name] NOT IN ('sp_alterdiagram','sp_creatediagram','sp_dropdiagram','sp_helpdiagramdefinition','sp_helpdiagrams','sp_renamediagram','sp_upgraddiagrams');", + "query": "SELECT s.[name] + '.' + so.[name] AS ObjectName FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] = 'P' AND so.[name] LIKE 'sp[_]%' AND so.[name] NOT IN ( 'sp_alterdiagram', 'sp_creatediagram', 'sp_dropdiagram', 'sp_helpdiagramdefinition', 'sp_helpdiagrams', 'sp_renamediagram', 'sp_upgraddiagrams' );", "transform": { "type": "aggregate", "map": { @@ -11444,7 +12352,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT s.[name] +'.'+so.[name] as ObjectName FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S' AND (so.[name] LIKE '% %' OR so.[name] LIKE '%[[]%' OR so.[name] LIKE '%]%' OR so.[name] LIKE '%-%' OR so.[name] LIKE '%.%' OR so.[name] LIKE '%,%' OR so.[name] LIKE '%;%' OR so.[name] LIKE '%' + CHAR(34) + '%' OR so.[name] LIKE '%' + CHAR(39) + '%');", + "query": "SELECT s.[name] + '.' + so.[name] as ObjectName FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S' AND ( so.[name] LIKE '% %' OR so.[name] LIKE '%[[]%' OR so.[name] LIKE '%]%' OR so.[name] LIKE '%-%' OR so.[name] LIKE '%.%' OR so.[name] LIKE '%,%' OR so.[name] LIKE '%;%' OR so.[name] LIKE '%' + CHAR(34) + '%' OR so.[name] LIKE '%' + CHAR(39) + '%' );", "transform": { "type": "aggregate", "map": { @@ -11464,7 +12372,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT s.name +'.'+ so.name + '.'+sc.name AS ObjectName FROM sys.columns sc INNER JOIN sys.objects so ON sc.object_id = so.object_id INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND (sc.[name] LIKE '% %' OR sc.[name] LIKE '%[[]%' OR sc.[name] LIKE '%]%' OR sc.[name] LIKE '%-%' OR sc.[name] LIKE '%.%' OR sc.[name] LIKE '%,%' OR sc.[name] LIKE '%;%' OR sc.[name] LIKE '%' + CHAR(34) + '%' OR sc.[name] LIKE '%' + CHAR(39) + '%') ORDER BY 1;", + "query": "SELECT s.name + '.' + so.name + '.' + sc.name AS ObjectName FROM sys.columns AS sc WITH (NOLOCK) INNER JOIN sys.objects AS so WITH (NOLOCK) ON sc.object_id = so.object_id INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND ( sc.[name] LIKE '% %' OR sc.[name] LIKE '%[[]%' OR sc.[name] LIKE '%]%' OR sc.[name] LIKE '%-%' OR sc.[name] LIKE '%.%' OR sc.[name] LIKE '%,%' OR sc.[name] LIKE '%;%' OR sc.[name] LIKE '%' + CHAR(34) + '%' OR sc.[name] LIKE '%' + CHAR(39) + '%' ) ORDER BY 1;", "transform": { "type": "aggregate", "map": { @@ -11484,7 +12392,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT s.name+'.'+so.name AS ObjectName FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] IN ('FN','FS','TF','IF') AND so.[name] LIKE 'fn[_]%' AND so.[name] NOT IN ('fn_diagram_objects')", + "query": "SELECT s.name + '.' + so.name AS ObjectName FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] IN ('FN', 'FS', 'TF', 'IF') AND so.[name] LIKE 'fn[_]%' AND so.[name] NOT IN ('fn_diagram_objects')", "transform": { "type": "aggregate", "map": { @@ -11505,10 +12413,10 @@ "implementation": { "useDatabase": true, "query": [ - "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('ABSOLUTE'), ('ACTION'), ('ADA'), ('ADD'), ('ADMIN'), ('AFTER'), ('AGGREGATE'), ('ALIAS'), ('ALL'), ('ALLOCATE'), ('ALTER'), ('AND'), ('ANY'), ('ARE'), ('ARRAY'), ('AS'), ('ASC'), ('ASSERTION'), ('AT'), ('AUTHORIZATION'), ('AVG'), ('BACKUP'), ('BEFORE'), ('BEGIN'), ('BETWEEN'), ('BINARY'), ('BIT'), ('BIT_LENGTH'), ('BLOB'), ('BOOLEAN'), ('BOTH'), ('BREADTH'), ('BREAK'), ('BROWSE'), ('BULK'), ('BY'), ('CALL'), ('CASCADE'), ('CASCADED'), ('CASE'), ('CAST'), ('CATALOG'), ('CHAR'), ('CHAR_LENGTH'), ('CHARACTER'), ('CHARACTER_LENGTH'), ('CHECK'), ('CHECKPOINT'), ('CLASS'), ('CLOB'), ('CLOSE'), ('CLUSTERED'), ('COALESCE'), ('COLLATE'), ('COLLATION'), ('COLUMN'), ('COMMIT'), ('COMPLETION'), ('COMPUTE'), ('CONNECT'), ('CONNECTION'), ('CONSTRAINT'), ('CONSTRAINTS'), ('CONSTRUCTOR'), ('CONTAINS'), ('CONTAINSTABLE'), ('CONTINUE'), ('CONVERT'), ('CORRESPONDING'), ('COUNT'), ('CREATE'), ('CROSS'), ('CUBE'), ('CURRENT'), ('CURRENT_DATE'), ('CURRENT_PATH'), ('CURRENT_ROLE'), ('CURRENT_TIME'), ('CURRENT_TIMESTAMP'), ('CURRENT_USER'), ('CURSOR'), ('CYCLE'), ('DATA'), ('DATABASE'), ('DATE'), ('DAY'), ('DBCC'), ('DEALLOCATE'), ('DEC'), ('DECIMAL'), ('DECLARE'), ('DEFAULT'), ('DEFERRABLE'), ('DEFERRED'), ('DELETE'), ('DENY'), ('DEPTH'), ('DEREF'), ('DESC'), ('DESCRIBE'), ('DESCRIPTOR'), ('DESTROY'), ('DESTRUCTOR'), ('DETERMINISTIC'), ('DIAGNOSTICS'), ('DICTIONARY'), ('DISCONNECT'), ('DISK'), ('DISTINCT'), ('DISTRIBUTED'), ('DOMAIN'), ('DOUBLE'), ('DROP'), ('DUMMY'), ('DUMP'), ('DYNAMIC') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", - "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('EACH'), ('ELSE'), ('END'), ('END-EXEC'), ('EQUALS'), ('ERRLVL'), ('ESCAPE'), ('EVERY'), ('EXCEPT'), ('EXCEPTION'), ('EXEC'), ('EXECUTE'), ('EXISTS'), ('EXIT'), ('EXTERNAL'), ('EXTRACT'), ('FALSE'), ('FETCH'), ('FILE'), ('FILLFACTOR'), ('FIRST'), ('FLOAT'), ('FOR'), ('FOREIGN'), ('FORTRAN'), ('FOUND'), ('FREE'), ('FREETEXT'), ('FREETEXTTABLE'), ('FROM'), ('FULL'), ('FULLTEXTTABLE'), ('FUNCTION'), ('GENERAL'), ('GET'), ('GLOBAL'), ('GO'), ('GOTO'), ('GRANT'), ('GROUP'), ('GROUPING'), ('HAVING'), ('HOLDLOCK'), ('HOST'), ('HOUR'), ('IDENTITY'), ('IDENTITY_INSERT'), ('IDENTITYCOL'), ('IF'), ('IGNORE'), ('IMMEDIATE'), ('IN'), ('INCLUDE'), ('INDEX'), ('INDICATOR'), ('INITIALIZE'), ('INITIALLY'), ('INNER'), ('INOUT'), ('INPUT'), ('INSENSITIVE'), ('INSERT'), ('INT'), ('INTEGER'), ('INTERSECT'), ('INTERVAL'), ('INTO'), ('IS'), ('ISOLATION'), ('ITERATE'), ('JOIN'), ('KEY'), ('KILL'), ('LANGUAGE'), ('LARGE'), ('LAST'), ('LATERAL'), ('LEADING'), ('LEFT'), ('LESS'), ('LEVEL'), ('LIKE'), ('LIMIT'), ('LINENO'), ('LOAD'), ('LOCAL'), ('LOCALTIME'), ('LOCALTIMESTAMP'), ('LOCATOR'), ('LOWER'), ('MAP'), ('MATCH'), ('MAX'), ('MIN'), ('MINUTE'), ('MODIFIES'), ('MODIFY'), ('MODULE'), ('MONTH') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", - "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('NAMES'), ('NATIONAL'), ('NATURAL'), ('NCHAR'), ('NCLOB'), ('NEW'), ('NEXT'), ('NO'), ('NOCHECK'), ('NONCLUSTERED'), ('NONE'), ('NOT'), ('NULL'), ('NULLIF'), ('NUMERIC'), ('OBJECT'), ('OCTET_LENGTH'), ('OF'), ('OFF'), ('OFFSETS'), ('OLD'), ('ON'), ('ONLY'), ('OPEN'), ('OPENDATASOURCE'), ('OPENQUERY'), ('OPENROWSET'), ('OPENXML'), ('OPERATION'), ('OPTION'), ('OR'), ('ORDER'), ('ORDINALITY'), ('OUT'), ('OUTER'), ('OUTPUT'), ('OVER'), ('OVERLAPS'), ('PAD'), ('PARAMETER'), ('PARAMETERS'), ('PARTIAL'), ('PASCAL'), ('PATH'), ('PERCENT'), ('PLAN'), ('POSITION'), ('POSTFIX'), ('PRECISION'), ('PREFIX'), ('PREORDER'), ('PREPARE'), ('PRESERVE'), ('PRIMARY'), ('PRINT'), ('PRIOR'), ('PRIVILEGES'), ('PROC'), ('PROCEDURE'), ('PUBLIC'), ('RAISERROR'), ('READ'), ('READS'), ('READTEXT'), ('REAL'), ('RECONFIGURE'), ('RECURSIVE'), ('REF'), ('REFERENCES'), ('REFERENCING'), ('RELATIVE'), ('REPLICATION'), ('RESTORE'), ('RESTRICT'), ('RESULT'), ('RETURN'), ('RETURNS'), ('REVOKE'), ('RIGHT'), ('ROLE'), ('ROLLBACK'), ('ROLLUP'), ('ROUTINE'), ('ROW'), ('ROWCOUNT'), ('ROWGUIDCOL'), ('ROWS'), ('RULE') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", - "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('SAVE'), ('SAVEPOINT'), ('SCHEMA'), ('SCOPE'), ('SCROLL'), ('SEARCH'), ('SECOND'), ('SECTION'), ('SELECT'), ('SEQUENCE'), ('SESSION'), ('SESSION_USER'), ('SET'), ('SETS'), ('SETUSER'), ('SHUTDOWN'), ('SIZE'), ('SMALLINT'), ('SOME'), ('SPACE'), ('SPECIFIC'), ('SPECIFICTYPE'), ('SQL'), ('SQLCA'), ('SQLCODE'), ('SQLERROR'), ('SQLEXCEPTION'), ('SQLSTATE'), ('SQLWARNING'), ('START'), ('STATE'), ('STATEMENT'), ('STATIC'), ('STATISTICS'), ('STRUCTURE'), ('SUBSTRING'), ('SUM'), ('SYSTEM_USER'), ('TABLE'), ('TEMPORARY'), ('TERMINATE'), ('TEXTSIZE'), ('THAN'), ('THEN'), ('TIME'), ('TIMESTAMP'), ('TIMEZONE_HOUR'), ('TIMEZONE_MINUTE'), ('TO'), ('TOP'), ('TRAILING'), ('TRAN'), ('TRANSACTION'), ('TRANSLATE'), ('TRANSLATION'), ('TREAT'), ('TRIGGER'), ('TRIM'), ('TRUE'), ('TRUNCATE'), ('UNDER'), ('UNION'), ('UNIQUE'), ('UNKNOWN'), ('UNNEST'), ('UPDATE'), ('UPDATETEXT'), ('UPPER'), ('USAGE'), ('USE'), ('USER'), ('USING'), ('VALUE'), ('VALUES'), ('VARCHAR'), ('VARIABLE'), ('VARYING'), ('VIEW'), ('WAITFOR'), ('WHEN'), ('WHENEVER'), ('WHERE'), ('WHILE'), ('WITH'), ('WITHOUT'), ('WORK'), ('WRITE'), ('WRITETEXT'), ('YEAR'), ('ZONE') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects so INNER JOIN sys.schemas s ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT" + "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('ABSOLUTE'), ('ACTION'), ('ADA'), ('ADD'), ('ADMIN'), ('AFTER'), ('AGGREGATE'), ('ALIAS'), ('ALL'), ('ALLOCATE'), ('ALTER'), ('AND'), ('ANY'), ('ARE'), ('ARRAY'), ('AS'), ('ASC'), ('ASSERTION'), ('AT'), ('AUTHORIZATION'), ('AVG'), ('BACKUP'), ('BEFORE'), ('BEGIN'), ('BETWEEN'), ('BINARY'), ('BIT'), ('BIT_LENGTH'), ('BLOB'), ('BOOLEAN'), ('BOTH'), ('BREADTH'), ('BREAK'), ('BROWSE'), ('BULK'), ('BY'), ('CALL'), ('CASCADE'), ('CASCADED'), ('CASE'), ('CAST'), ('CATALOG'), ('CHAR'), ('CHAR_LENGTH'), ('CHARACTER'), ('CHARACTER_LENGTH'), ('CHECK'), ('CHECKPOINT'), ('CLASS'), ('CLOB'), ('CLOSE'), ('CLUSTERED'), ('COALESCE'), ('COLLATE'), ('COLLATION'), ('COLUMN'), ('COMMIT'), ('COMPLETION'), ('COMPUTE'), ('CONNECT'), ('CONNECTION'), ('CONSTRAINT'), ('CONSTRAINTS'), ('CONSTRUCTOR'), ('CONTAINS'), ('CONTAINSTABLE'), ('CONTINUE'), ('CONVERT'), ('CORRESPONDING'), ('COUNT'), ('CREATE'), ('CROSS'), ('CUBE'), ('CURRENT'), ('CURRENT_DATE'), ('CURRENT_PATH'), ('CURRENT_ROLE'), ('CURRENT_TIME'), ('CURRENT_TIMESTAMP'), ('CURRENT_USER'), ('CURSOR'), ('CYCLE'), ('DATA'), ('DATABASE'), ('DATE'), ('DAY'), ('DBCC'), ('DEALLOCATE'), ('DEC'), ('DECIMAL'), ('DECLARE'), ('DEFAULT'), ('DEFERRABLE'), ('DEFERRED'), ('DELETE'), ('DENY'), ('DEPTH'), ('DEREF'), ('DESC'), ('DESCRIBE'), ('DESCRIPTOR'), ('DESTROY'), ('DESTRUCTOR'), ('DETERMINISTIC'), ('DIAGNOSTICS'), ('DICTIONARY'), ('DISCONNECT'), ('DISK'), ('DISTINCT'), ('DISTRIBUTED'), ('DOMAIN'), ('DOUBLE'), ('DROP'), ('DUMMY'), ('DUMP'), ('DYNAMIC') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", + "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('EACH'), ('ELSE'), ('END'), ('END-EXEC'), ('EQUALS'), ('ERRLVL'), ('ESCAPE'), ('EVERY'), ('EXCEPT'), ('EXCEPTION'), ('EXEC'), ('EXECUTE'), ('EXISTS'), ('EXIT'), ('EXTERNAL'), ('EXTRACT'), ('FALSE'), ('FETCH'), ('FILE'), ('FILLFACTOR'), ('FIRST'), ('FLOAT'), ('FOR'), ('FOREIGN'), ('FORTRAN'), ('FOUND'), ('FREE'), ('FREETEXT'), ('FREETEXTTABLE'), ('FROM'), ('FULL'), ('FULLTEXTTABLE'), ('FUNCTION'), ('GENERAL'), ('GET'), ('GLOBAL'), ('GO'), ('GOTO'), ('GRANT'), ('GROUP'), ('GROUPING'), ('HAVING'), ('HOLDLOCK'), ('HOST'), ('HOUR'), ('IDENTITY'), ('IDENTITY_INSERT'), ('IDENTITYCOL'), ('IF'), ('IGNORE'), ('IMMEDIATE'), ('IN'), ('INCLUDE'), ('INDEX'), ('INDICATOR'), ('INITIALIZE'), ('INITIALLY'), ('INNER'), ('INOUT'), ('INPUT'), ('INSENSITIVE'), ('INSERT'), ('INT'), ('INTEGER'), ('INTERSECT'), ('INTERVAL'), ('INTO'), ('IS'), ('ISOLATION'), ('ITERATE'), ('JOIN'), ('KEY'), ('KILL'), ('LANGUAGE'), ('LARGE'), ('LAST'), ('LATERAL'), ('LEADING'), ('LEFT'), ('LESS'), ('LEVEL'), ('LIKE'), ('LIMIT'), ('LINENO'), ('LOAD'), ('LOCAL'), ('LOCALTIME'), ('LOCALTIMESTAMP'), ('LOCATOR'), ('LOWER'), ('MAP'), ('MATCH'), ('MAX'), ('MIN'), ('MINUTE'), ('MODIFIES'), ('MODIFY'), ('MODULE'), ('MONTH') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", + "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('NAMES'), ('NATIONAL'), ('NATURAL'), ('NCHAR'), ('NCLOB'), ('NEW'), ('NEXT'), ('NO'), ('NOCHECK'), ('NONCLUSTERED'), ('NONE'), ('NOT'), ('NULL'), ('NULLIF'), ('NUMERIC'), ('OBJECT'), ('OCTET_LENGTH'), ('OF'), ('OFF'), ('OFFSETS'), ('OLD'), ('ON'), ('ONLY'), ('OPEN'), ('OPENDATASOURCE'), ('OPENQUERY'), ('OPENROWSET'), ('OPENXML'), ('OPERATION'), ('OPTION'), ('OR'), ('ORDER'), ('ORDINALITY'), ('OUT'), ('OUTER'), ('OUTPUT'), ('OVER'), ('OVERLAPS'), ('PAD'), ('PARAMETER'), ('PARAMETERS'), ('PARTIAL'), ('PASCAL'), ('PATH'), ('PERCENT'), ('PLAN'), ('POSITION'), ('POSTFIX'), ('PRECISION'), ('PREFIX'), ('PREORDER'), ('PREPARE'), ('PRESERVE'), ('PRIMARY'), ('PRINT'), ('PRIOR'), ('PRIVILEGES'), ('PROC'), ('PROCEDURE'), ('PUBLIC'), ('RAISERROR'), ('READ'), ('READS'), ('READTEXT'), ('REAL'), ('RECONFIGURE'), ('RECURSIVE'), ('REF'), ('REFERENCES'), ('REFERENCING'), ('RELATIVE'), ('REPLICATION'), ('RESTORE'), ('RESTRICT'), ('RESULT'), ('RETURN'), ('RETURNS'), ('REVOKE'), ('RIGHT'), ('ROLE'), ('ROLLBACK'), ('ROLLUP'), ('ROUTINE'), ('ROW'), ('ROWCOUNT'), ('ROWGUIDCOL'), ('ROWS'), ('RULE') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT", + "DECLARE @KeywordTbl AS TABLE(Keyword VARCHAR(255)) INSERT INTO @KeywordTbl VALUES ('SAVE'), ('SAVEPOINT'), ('SCHEMA'), ('SCOPE'), ('SCROLL'), ('SEARCH'), ('SECOND'), ('SECTION'), ('SELECT'), ('SEQUENCE'), ('SESSION'), ('SESSION_USER'), ('SET'), ('SETS'), ('SETUSER'), ('SHUTDOWN'), ('SIZE'), ('SMALLINT'), ('SOME'), ('SPACE'), ('SPECIFIC'), ('SPECIFICTYPE'), ('SQL'), ('SQLCA'), ('SQLCODE'), ('SQLERROR'), ('SQLEXCEPTION'), ('SQLSTATE'), ('SQLWARNING'), ('START'), ('STATE'), ('STATEMENT'), ('STATIC'), ('STATISTICS'), ('STRUCTURE'), ('SUBSTRING'), ('SUM'), ('SYSTEM_USER'), ('TABLE'), ('TEMPORARY'), ('TERMINATE'), ('TEXTSIZE'), ('THAN'), ('THEN'), ('TIME'), ('TIMESTAMP'), ('TIMEZONE_HOUR'), ('TIMEZONE_MINUTE'), ('TO'), ('TOP'), ('TRAILING'), ('TRAN'), ('TRANSACTION'), ('TRANSLATE'), ('TRANSLATION'), ('TREAT'), ('TRIGGER'), ('TRIM'), ('TRUE'), ('TRUNCATE'), ('UNDER'), ('UNION'), ('UNIQUE'), ('UNKNOWN'), ('UNNEST'), ('UPDATE'), ('UPDATETEXT'), ('UPPER'), ('USAGE'), ('USE'), ('USER'), ('USING'), ('VALUE'), ('VALUES'), ('VARCHAR'), ('VARIABLE'), ('VARYING'), ('VIEW'), ('WAITFOR'), ('WHEN'), ('WHENEVER'), ('WHERE'), ('WHILE'), ('WITH'), ('WITHOUT'), ('WORK'), ('WRITE'), ('WRITETEXT'), ('YEAR'), ('ZONE') SELECT [schema]+'.'+[ObjName] AS ObjectName FROM ( SELECT s.name [schema], so.name [ObjName], type, type_desc FROM sys.objects AS so WITH (NOLOCK) INNER JOIN sys.schemas AS s WITH (NOLOCK) ON so.schema_id = s.schema_id WHERE so.is_ms_shipped = 0 AND [type] <> 'S') AS ObjNames CROSS JOIN @KeywordTbl WHERE ObjName like '% '+Keyword+' %' COLLATE DATABASE_DEFAULT OR ObjName like '% '+Keyword COLLATE DATABASE_DEFAULT OR ObjName = Keyword COLLATE DATABASE_DEFAULT" ], "transform": { "type": "aggregate", @@ -11611,7 +12519,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT ss.[name]+'.'+t.[name]+'.'+i.[name] as IndexName FROM [sys].[indexes] AS i INNER JOIN [sys].[tables] AS t ON t.[object_id]=i.[object_id] INNER JOIN [sys].[schemas] ss ON ss.[schema_id]=t.[schema_id] INNER JOIN [sys].[index_columns] AS sic ON sic.[object_id]=t.[object_id] AND sic.index_id=i.index_id INNER JOIN [sys].[columns] AS sc ON sc.[object_id]=t.[object_id] AND sc.column_id=sic.column_id INNER JOIN [sys].[types] AS sty ON sc.user_type_id=sty.user_type_id WHERE sic.is_included_column=0 AND sty.name='uniqueidentifier' and i.type=1 AND i.is_unique_constraint=0 AND t.is_ms_shipped=0 GROUP BY ss.name,t.[name],i.name HAVING COUNT(sty.name)>0", + "query": "SELECT CONCAT(ss.[name], '.', t.[name], '.', i.[name]) AS IndexName FROM [sys].[indexes] AS i WITH (NOLOCK) INNER JOIN [sys].[tables] AS t WITH (NOLOCK) ON t.[object_id] = i.[object_id] INNER JOIN [sys].[schemas] AS ss WITH (NOLOCK) ON ss.[schema_id] = t.[schema_id] INNER JOIN [sys].[index_columns] AS sic WITH (NOLOCK) ON sic.[object_id] = t.[object_id] AND sic.index_id = i.index_id INNER JOIN [sys].[columns] AS sc WITH (NOLOCK) ON sc.[object_id] = t.[object_id] AND sc.column_id = sic.column_id INNER JOIN [sys].[types] AS sty WITH (NOLOCK) ON sc.user_type_id = sty.user_type_id WHERE sic.is_included_column = 0 AND sty.name = 'uniqueidentifier' and i.type = 1 AND i.is_unique_constraint = 0 AND t.is_ms_shipped = 0 GROUP BY ss.name, t.[name], i.name HAVING COUNT(sty.name) > 0", "transform": { "type": "aggregate", "map": { @@ -11633,7 +12541,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "IF (SELECT COUNT(*) FROM msdb.dbo.suspect_pages WHERE (event_type = 1 OR event_type = 2 OR event_type = 3)) > 0 BEGIN SELECT CASE event_type WHEN 1 THEN 'Error 823 or unspecified Error 824' WHEN 2 THEN 'Bad Checksum' WHEN 3 THEN 'Torn Page' ELSE NULL END AS [EventType] FROM msdb.dbo.suspect_pages (NOLOCK) WHERE (event_type = 1 OR event_type = 2 OR event_type = 3) AND DB_NAME(database_id)=(@TargetName) END;" + "query": "IF ( SELECT COUNT(*) FROM msdb.dbo.suspect_pages WITH (NOLOCK) WHERE ( event_type = 1 OR event_type = 2 OR event_type = 3 ) ) > 0 BEGIN SELECT CASE event_type WHEN 1 THEN 'Error 823 or unspecified Error 824' WHEN 2 THEN 'Bad Checksum' WHEN 3 THEN 'Torn Page' ELSE NULL END AS [EventType] FROM msdb.dbo.suspect_pages (NOLOCK) WHERE ( event_type = 1 OR event_type = 2 OR event_type = 3 ) AND DB_NAME(database_id) =(@TargetName) END;" } } ], @@ -11649,7 +12557,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "IF (SELECT COUNT(sd.database_id) FROM sys.databases sd INNER JOIN sys.master_files smf ON sd.database_id = smf.database_id WHERE sd.source_database_id IS NULL AND smf.is_sparse = 1) > 0 BEGIN SELECT 'Database_checks' AS [Category], 'DB_nonSnap_Sparse' AS [Information], DB_NAME(sd.database_id) AS database_name, smf.name AS [SparseFiles], smf.physical_name FROM sys.databases sd INNER JOIN sys.master_files smf ON sd.database_id = smf.database_id WHERE sd.source_database_id IS NULL AND smf.is_sparse = 1 AND DB_NAME(sd.database_id)=@TargetName END;" + "query": "IF ( SELECT COUNT(sd.database_id) FROM sys.databases AS sd WITH (NOLOCK) INNER JOIN sys.master_files AS smf WITH (NOLOCK) ON sd.database_id = smf.database_id WHERE sd.source_database_id IS NULL AND smf.is_sparse = 1 ) > 0 BEGIN SELECT 'Database_checks' AS [Category], 'DB_nonSnap_Sparse' AS [Information], DB_NAME(sd.database_id) AS database_name, smf.name AS [SparseFiles], smf.physical_name FROM sys.databases AS sd WITH (NOLOCK) INNER JOIN sys.master_files AS smf WITH (NOLOCK) ON sd.database_id = smf.database_id WHERE sd.source_database_id IS NULL AND smf.is_sparse = 1 AND DB_NAME(sd.database_id) = @TargetName END;" } } ], @@ -11689,52 +12597,6 @@ } } ], - "NullPassword": [ - { - "type": "SQL", - "target": { - "type": "Server", - "platform": [ - "Windows", - "Linux" - ], - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "implementation": { - "query": "SELECT RTRIM(name) AS [PasswordData] FROM master.sys.sql_logins WHERE [password_hash] IS NULL AND name NOT IN ('MSCRMSqlClrLogin','##MS_SmoExtendedSigningCertificate##','##MS_PolicySigningCertificate##','##MS_SQLResourceSigningCertificate##','##MS_SQLReplicationSigningCertificate##','##MS_SQLAuthenticatorCertificate##','##MS_AgentSigningCertificate##','##MS_SQLEnableSystemAssemblyLoadingUser##')", - "transform": { - "type": "aggregate", - "map": { - "PasswordData": "join" - } - } - } - } - ], - "NamePassword": [ - { - "type": "SQL", - "target": { - "type": "Server", - "platform": [ - "Windows", - "Linux" - ], - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "implementation": { - "query": "SELECT DISTINCT RTRIM(s.name) AS [PasswordData] FROM master.sys.sql_logins s WHERE PWDCOMPARE(RTRIM(RTRIM(s.name)), s.[password_hash]) = 1", - "transform": { - "type": "aggregate", - "map": { - "PasswordData": "join" - } - } - } - } - ], "SystemHealth": [ { "type": "SQL", @@ -11763,7 +12625,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT compatibility_level as [CompatibilityLevel] FROM sys.databases where name=@TargetName" + "query": "SELECT compatibility_level as [CompatibilityLevel] FROM sys.databases WITH (NOLOCK) where name = @TargetName" } } ], @@ -11819,7 +12681,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT CONCAT( sh.[name], '.', o.[name] ) AS FullName, CAST(sp.rows_sampled/(sp.[rows]*1.00) AS DECIMAL(5,2)) AS stat_sampling_rate FROM sys.objects AS o INNER JOIN sys.tables AS mst ON mst.[object_id] = o.[object_id] INNER JOIN sys.stats AS ss ON ss.[object_id] = o.[object_id] INNER JOIN sys.schemas AS sh ON sh.[schema_id] = o.[schema_id] CROSS APPLY sys.dm_db_stats_properties(o.[object_id], ss.[stats_id]) AS sp WHERE sp.[rows] > 0 AND sp.rows_sampled/(sp.[rows]*1.00) < @threshold" + "query": "SELECT CONCAT(sh.[name], '.', o.[name]) AS FullName, CAST(sp.rows_sampled /(sp.[rows] * 1.00) AS DECIMAL(5, 2)) AS stat_sampling_rate FROM sys.objects AS o WITH (NOLOCK) INNER JOIN sys.tables AS mst WITH (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.stats AS ss WITH (NOLOCK) ON ss.[object_id] = o.[object_id] INNER JOIN sys.schemas AS sh WITH (NOLOCK) ON sh.[schema_id] = o.[schema_id] CROSS APPLY sys.dm_db_stats_properties(o.[object_id], ss.[stats_id]) AS sp WHERE sp.[rows] > 0 AND sp.rows_sampled /(sp.[rows] * 1.00) < @threshold" } } ], @@ -11837,7 +12699,7 @@ "implementation": { "useDatabase": true, "timeout": 180, - "query": "SELECT CASE si.type WHEN 0 THEN CONCAT(t.[name], '.', mst.[name], ' (HEAP)') ELSE CONCAT(t.[name], '.', mst.[name], '.', si.name) END AS IndexFullName, index_stat.fragmentation, index_stat.page_count, si.type AS IndexType FROM sys.indexes si INNER JOIN sys.partitions sp ON si.[object_id] = sp.[object_id] AND si.index_id = sp.index_id INNER JOIN sys.tables AS mst ON mst.[object_id] = si.[object_id] INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id] LEFT JOIN ( SELECT ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, SUM(ps.avg_fragmentation_in_percent) AS fragmentation, SUM(ps.page_count) [page_count] FROM sys.dm_db_index_physical_stats(DB_ID(@TargetName), NULL, NULL, NULL, NULL) ps WHERE ps.index_level = 0 AND ps.alloc_unit_type_desc = 'IN_ROW_DATA' GROUP BY ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, ps.record_count, ps.forwarded_record_count ) index_stat on index_stat.[object_id] = si.[object_id] AND index_stat.index_id = si.index_id AND index_stat.[partition_number] = sp.partition_number WHERE mst.is_ms_shipped = 0 AND si.[type] IN (0, 1, 2)" + "query": "SELECT CASE i.[type] WHEN 0 THEN CONCAT(SCHEMA_NAME(t.schema_id), '.', t.[name], ' (HEAP)') ELSE CONCAT(SCHEMA_NAME(t.schema_id), '.', t.[name], '.', i.[name]) END AS IndexFullName, stat.fragmentation, stat.page_count, i.[type] AS IndexType FROM sys.indexes AS i WITH (NOLOCK) INNER JOIN sys.tables AS t WITH (NOLOCK) ON t.[object_id] = i.[object_id] AND t.is_ms_shipped = 0 INNER JOIN ( SELECT [object_id], index_id, SUM(ps.avg_fragmentation_in_percent) AS fragmentation, SUM(ps.page_count) AS page_count FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) ps WHERE ps.index_level = 0 AND ps.alloc_unit_type_desc = 'IN_ROW_DATA' GROUP BY [object_id], index_id ) stat ON stat.index_id = i.index_id AND stat.[object_id] = i.[object_id] WHERE i.[type] IN (0, 1, 2)" } }, { @@ -11853,7 +12715,7 @@ "implementation": { "useDatabase": true, "timeout": 180, - "query": "SELECT CASE si.type WHEN 0 THEN CONCAT(t.[name], '.', mst.[name], ' (HEAP)') ELSE CONCAT(t.[name], '.', mst.[name], '.', si.name) END AS IndexFullName, ISNULL(index_stat.fragmentation, 0) AS fragmentation, ISNULL(index_stat.page_count, 0) AS page_count, ISNULL(index_stat_ci.fragmentation_CI, 0) AS fragmentation_CI, ISNULL(index_stat_ci.state, 0) AS state, si.type AS IndexType FROM sys.indexes si INNER JOIN sys.partitions sp ON si.[object_id] = sp.[object_id] AND si.index_id = sp.index_id INNER JOIN sys.tables AS mst ON mst.[object_id] = si.[object_id] INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id] LEFT JOIN ( SELECT ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, SUM(ps.avg_fragmentation_in_percent) AS fragmentation, SUM(ps.page_count) [page_count] FROM sys.dm_db_index_physical_stats(DB_ID(@TargetName), NULL, NULL, NULL, NULL) ps WHERE ps.index_level = 0 AND ps.alloc_unit_type_desc = 'IN_ROW_DATA' GROUP BY ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, ps.record_count, ps.forwarded_record_count ) index_stat on index_stat.[object_id] = si.[object_id] AND index_stat.index_id = si.index_id AND index_stat.[partition_number] = sp.partition_number LEFT JOIN ( SELECT rg.object_id, rg.index_id, rg.partition_number, SUM( (ISNULL(rg.deleted_rows, 1) * 100) /CASE WHEN rg.total_rows = 0 THEN 1 ELSE rg.total_rows END ) AS [fragmentation_CI], rg.[state] FROM sys.column_store_row_groups rg GROUP BY rg.object_id, rg.index_id, rg.partition_number, rg.total_rows, rg.delta_store_hobt_id, rg.row_group_id, rg.state ) index_stat_ci on index_stat_ci.[object_id] = si.[object_id] AND index_stat_ci.index_id = si.index_id AND index_stat_ci.[partition_number] = sp.[partition_number] WHERE mst.is_ms_shipped = 0 AND si.[type] IN (0, 1, 2, 5, 6, 7)" + "query": "SELECT CASE i.[type] WHEN 0 THEN CONCAT(SCHEMA_NAME(t.schema_id), '.', t.[name], ' (HEAP)') ELSE CONCAT(SCHEMA_NAME(t.schema_id), '.', t.[name], '.', i.[name]) END AS IndexFullName, stat.fragmentation, stat.page_count, 0 AS fragmentation_CI, 0 AS [state], i.[type] AS IndexType FROM sys.indexes AS i WITH (NOLOCK) INNER JOIN sys.tables AS t WITH (NOLOCK) ON t.[object_id] = i.[object_id] AND t.is_ms_shipped = 0 INNER JOIN ( SELECT [object_id], index_id, SUM(ps.avg_fragmentation_in_percent) AS fragmentation, SUM(ps.page_count) AS page_count FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) ps WHERE ps.index_level = 0 AND ps.alloc_unit_type_desc = 'IN_ROW_DATA' GROUP BY [object_id], index_id ) stat ON stat.index_id = i.index_id AND stat.[object_id] = i.[object_id] WHERE i.[type] IN (0, 1, 2, 7) UNION SELECT CONCAT(SCHEMA_NAME(t.schema_id), '.', t.[name], '.', i.[name]) AS IndexFullName, 0, 0, SUM( (ISNULL(rg.deleted_rows, 1) * 100) /CASE WHEN rg.total_rows = 0 THEN 1 ELSE rg.total_rows END ), rg.[state], i.[type] FROM sys.column_store_row_groups AS rg WITH (NOLOCK) INNER JOIN sys.indexes AS i WITH (NOLOCK) ON i.index_id = rg.index_id and i.[object_id] = rg.[object_id] INNER JOIN sys.tables AS t WITH (NOLOCK) ON t.[object_id] = rg.[object_id] AND t.is_ms_shipped = 0 GROUP BY rg.[object_id], i.[name], t.[name], t.[schema_id], rg.[state], i.[type]" } } ], @@ -11870,7 +12732,7 @@ }, "implementation": { "useDatabase": true, - "query": "IF NOT EXISTS( SELECT * FROM sys.filegroups where [type] = 'FX' ) RETURN; DECLARE @tmpXIS TABLE( [object_id] int, [schema_name] VARCHAR(100) COLLATE database_default, [table_name] VARCHAR(300) COLLATE database_default, [index_id] int, [index_name] VARCHAR(300) COLLATE database_default, total_bucket_count bigint, empty_bucket_count bigint, avg_chain_length bigint, max_chain_length bigint, KeyCols VARCHAR(4000) COLLATE database_default, DistinctCnt bigint NULL, isdone bit ) INSERT INTO @tmpXIS SELECT xis.[object_id], t.name, o.name, xis.index_id, si.name, xhis.total_bucket_count, xhis.empty_bucket_count, xhis.avg_chain_length, xhis.max_chain_length, SUBSTRING( ( SELECT ',' + ac.name FROM sys.tables AS st INNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id] INNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] INNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] WHERE si.[object_id] = i.[object_id] AND si.index_id = i.index_id AND ic.is_included_column = 0 ORDER BY ic.key_ordinal FOR XML PATH('') ), 2, 8000 ) AS KeyCols, NULL distinctCntOUT, 0 FROM sys.dm_db_xtp_hash_index_stats AS xhis INNER JOIN sys.dm_db_xtp_index_stats AS xis ON xis.[object_id] = xhis.[object_id] AND xis.[index_id] = xhis.[index_id] INNER JOIN sys.indexes AS si (NOLOCK) ON xis.[object_id] = si.[object_id] AND xis.[index_id] = si.[index_id] INNER JOIN sys.objects AS o (NOLOCK) ON si.[object_id] = o.[object_id] INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id] WHERE o.[type] = 'U' DECLARE @objectid int, @indexid int, @sqlcmd NVARCHAR(4000), @params NVARCHAR(500), @schema_name VARCHAR(100), @table_name VARCHAR(300), @KeyCols VARCHAR(4000), @distinctCnt bigint IF EXISTS ( SELECT TOP 1 [object_id] FROM @tmpXIS WHERE isdone = 0 ) BEGIN WHILE ( SELECT COUNT([object_id]) FROM @tmpXIS WHERE isdone = 0 ) > 0 BEGIN SELECT TOP 1 @objectid = [object_id], @indexid = [index_id], @schema_name = [schema_name], @table_name = [table_name], @KeyCols = KeyCols FROM @tmpXIS WHERE isdone = 0 SELECT @sqlcmd = 'SELECT @distinctCntOUT=COUNT(*) FROM (SELECT DISTINCT ' + @KeyCols + ' FROM ' + @schema_name + '.' + @table_name + ') t1;' EXECUTE sp_executesql @sqlcmd, N'@distinctCntOUT bigint OUTPUT', @distinctCntOUT = @distinctCnt OUTPUT UPDATE @tmpXIS SET DistinctCnt = @distinctCnt, isdone = 1 WHERE [object_id] = @objectid AND [index_id] = @indexid; END; END; SELECT CONCAT([schema_name], '.', table_name, '.', index_name) AS IndexFullName, FLOOR( ( CAST(empty_bucket_count AS FLOAT) / total_bucket_count ) * 100 ) EmptyBucketPct, total_bucket_count, avg_chain_length, DistinctCnt FROM @tmpXIS" + "query": "IF NOT EXISTS( SELECT * FROM sys.filegroups where [type] = 'FX' ) RETURN; DECLARE @tmpXIS TABLE( [object_id] int, [schema_name] VARCHAR(100) COLLATE database_default, [table_name] VARCHAR(300) COLLATE database_default, [index_id] int, [index_name] VARCHAR(300) COLLATE database_default, total_bucket_count bigint, empty_bucket_count bigint, avg_chain_length bigint, max_chain_length bigint, KeyCols VARCHAR(4000) COLLATE database_default, DistinctCnt bigint NULL, isdone bit ) INSERT INTO @tmpXIS SELECT xis.[object_id], t.name, o.name, xis.index_id, si.name, xhis.total_bucket_count, xhis.empty_bucket_count, xhis.avg_chain_length, xhis.max_chain_length, SUBSTRING( ( SELECT ',' + ac.name FROM sys.tables AS st WITH (NOLOCK) INNER JOIN sys.indexes AS i WITH (NOLOCK) ON st.[object_id] = i.[object_id] INNER JOIN sys.index_columns AS ic WITH (NOLOCK) ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] INNER JOIN sys.all_columns AS ac WITH (NOLOCK) ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id] WHERE si.[object_id] = i.[object_id] AND si.index_id = i.index_id AND ic.is_included_column = 0 ORDER BY ic.key_ordinal FOR XML PATH('') ), 2, 8000 ) AS KeyCols, NULL distinctCntOUT, 0 FROM sys.dm_db_xtp_hash_index_stats AS xhis INNER JOIN sys.dm_db_xtp_index_stats AS xis ON xis.[object_id] = xhis.[object_id] AND xis.[index_id] = xhis.[index_id] INNER JOIN sys.indexes AS si (NOLOCK) ON xis.[object_id] = si.[object_id] AND xis.[index_id] = si.[index_id] INNER JOIN sys.objects AS o (NOLOCK) ON si.[object_id] = o.[object_id] INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id] WHERE o.[type] = 'U' DECLARE @objectid int, @indexid int, @sqlcmd NVARCHAR(4000), @params NVARCHAR(500), @schema_name VARCHAR(100), @table_name VARCHAR(300), @KeyCols VARCHAR(4000), @distinctCnt bigint IF EXISTS ( SELECT TOP 1 [object_id] FROM @tmpXIS WHERE isdone = 0 ) BEGIN WHILE ( SELECT COUNT([object_id]) FROM @tmpXIS WHERE isdone = 0 ) > 0 BEGIN SELECT TOP 1 @objectid = [object_id], @indexid = [index_id], @schema_name = [schema_name], @table_name = [table_name], @KeyCols = KeyCols FROM @tmpXIS WHERE isdone = 0 SELECT @sqlcmd = 'SELECT @distinctCntOUT=COUNT(*) FROM (SELECT DISTINCT ' + @KeyCols + ' FROM ' + @schema_name + '.' + @table_name + ') t1;' EXECUTE sp_executesql @sqlcmd, N'@distinctCntOUT bigint OUTPUT', @distinctCntOUT = @distinctCnt OUTPUT UPDATE @tmpXIS SET DistinctCnt = @distinctCnt, isdone = 1 WHERE [object_id] = @objectid AND [index_id] = @indexid; END; END; SELECT CONCAT([schema_name], '.', table_name, '.', index_name) AS IndexFullName, FLOOR( ( CAST(empty_bucket_count AS FLOAT) / total_bucket_count ) * 100 ) EmptyBucketPct, total_bucket_count, avg_chain_length, DistinctCnt FROM @tmpXIS" } } ], @@ -11966,7 +12828,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT DISTINCT CONCAT(t.name,'.',OBJECT_NAME(mst.[object_id])) AS [TableName],ss.name AS [StatName],sp.[rows],sp.modification_counter,sp.rows_sampled FROM sys.objects AS o INNER JOIN sys.tables AS mst ON mst.[object_id]=o.[object_id] INNER JOIN sys.schemas AS t ON t.[schema_id]=mst.[schema_id] INNER JOIN sys.stats AS ss ON ss.[object_id]=mst.[object_id] CROSS APPLY sys.dm_db_stats_properties(ss.[object_id],ss.[stats_id]) AS sp WHERE sp.[rows]>0" + "query": "SELECT DISTINCT CONCAT(t.name, '.', OBJECT_NAME(mst.[object_id])) AS [TableName], ss.name AS [StatName], sp.[rows], sp.modification_counter, sp.rows_sampled FROM sys.objects AS o WITH (NOLOCK) INNER JOIN sys.tables AS mst WITH (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas AS t WITH (NOLOCK) ON t.[schema_id] = mst.[schema_id] INNER JOIN sys.stats AS ss WITH (NOLOCK) ON ss.[object_id] = mst.[object_id] CROSS APPLY sys.dm_db_stats_properties(ss.[object_id], ss.[stats_id]) AS sp WHERE sp.[rows] > 0" } }, { @@ -11981,7 +12843,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT DISTINCT CONCAT(t.name, '.', OBJECT_NAME(mst.[object_id])) AS [TableName], ss.name AS [StatName], SUM(p.[rows]) AS [rows], si.rowmodctr AS modification_counter, 0 AS rows_sampled FROM sys.sysindexes AS si INNER JOIN sys.objects AS o ON si.id = o.[object_id] INNER JOIN sys.tables AS mst ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id] INNER JOIN sys.stats AS ss ON ss.[object_id] = o.[object_id] INNER JOIN sys.partitions AS p ON p.[object_id] = ss.[object_id] LEFT JOIN sys.indexes i ON si.id = i.[object_id] AND si.indid = i.index_id WHERE o.type <> 'S' AND i.name IS NOT NULL GROUP BY mst.[object_id], t.name, rowmodctr, ss.name HAVING SUM(p.[rows]) > 0" + "query": "SELECT DISTINCT CONCAT(t.name, '.', OBJECT_NAME(mst.[object_id])) AS [TableName], ss.name AS [StatName], SUM(p.[rows]) AS [rows], si.rowmodctr AS modification_counter, 0 AS rows_sampled FROM sys.sysindexes AS si WITH (NOLOCK) INNER JOIN sys.objects AS o WITH (NOLOCK) ON si.id = o.[object_id] INNER JOIN sys.tables AS mst WITH (NOLOCK) ON mst.[object_id] = o.[object_id] INNER JOIN sys.schemas AS t WITH (NOLOCK) ON t.[schema_id] = mst.[schema_id] INNER JOIN sys.stats AS ss WITH (NOLOCK) ON ss.[object_id] = o.[object_id] INNER JOIN sys.partitions AS p WITH (NOLOCK) ON p.[object_id] = ss.[object_id] LEFT JOIN sys.indexes i WITH (NOLOCK) ON si.id = i.[object_id] AND si.indid = i.index_id WHERE o.type <> 'S' AND i.name IS NOT NULL GROUP BY mst.[object_id], t.name, rowmodctr, ss.name HAVING SUM(p.[rows]) > 0" } } ], @@ -12104,7 +12966,7 @@ "type": "SQL", "target": { "type": "Server", - "engineEdition": "SqlServer", + "engineEdition": "SqlServer, ManagedInstance", "platform": [ "Windows", "Linux" @@ -12458,7 +13320,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT DISTINCT CASE WHEN LEFT(physical_name, 1)= '\\' THEN LEFT(physical_name, charindex('\\',physical_name,5)) ELSE LEFT(physical_name,3) END AS [masterFilesVolumeName] FROM sys.master_files WHERE [database_id] <> 32767;" + "query": "SELECT DISTINCT CASE WHEN LEFT(physical_name, 1)= '\\' THEN LEFT(physical_name, charindex('\\',physical_name,5)) ELSE LEFT(physical_name,3) END AS [masterFilesVolumeName] FROM sys.master_files WITH (NOLOCK) WHERE [database_id] <> 32767;" } } ], @@ -12479,6 +13341,114 @@ } } ], + "AGConfiguration": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[11.0, 13.0)" + }, + "runFor": { + "feature": [ + "HADR" + ] + }, + "implementation": { + "query": "SELECT ag.group_id AS ag_id, ag.[name] AS ag_name, ar.replica_id, ar.replica_server_name AS ag_replica_server, ar_state.is_local AS is_ag_replica_local, ar.availability_mode, ar.availability_mode_desc, ar.failover_mode, ar.failover_mode_desc, ar_state.[role] AS ag_replica_role, ar_state.role_desc AS ag_replica_role_desc, ar_state.operational_state AS ag_replica_operational_state, ISNULL(ar_state.operational_state_desc, 'UNKNOWN') AS ag_replica_operational_state_desc, ar_state.connected_state AS ag_replica_connected_state, ar_state.synchronization_health AS ag_replica_synchronization_health, ar.secondary_role_allow_connections, ar.secondary_role_allow_connections_desc, avg_state.primary_recovery_health, avg_state.primary_recovery_health_desc, avg_state.synchronization_health, avg_state.synchronization_health_desc, ar.backup_priority, ag.automated_backup_preference, ag.automated_backup_preference_desc, ag.failure_condition_level, ag.health_check_timeout, ar.session_timeout, ar.endpoint_url, CASE WHEN loc_r.replica_id IS NOT NULL THEN 1 ELSE 0 END AS is_on_primary_replica, 0 AS is_distributed FROM sys.availability_groups AS ag WITH (NOLOCK) INNER JOIN sys.availability_replicas AS ar WITH (NOLOCK) ON ag.group_id = ar.group_id INNER JOIN sys.dm_hadr_availability_replica_states AS ar_state WITH (NOLOCK) ON ar.replica_id = ar_state.replica_id INNER JOIN sys.dm_hadr_availability_group_states AS avg_state WITH (NOLOCK) ON avg_state.group_id = ag.group_id LEFT JOIN sys.dm_hadr_availability_replica_states AS loc_r WITH (NOLOCK) ON loc_r.is_local = 1 AND loc_r.[role] = 1 AND loc_r.group_id = ag.group_id" + } + }, + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[13.0,)" + }, + "runFor": { + "feature": [ + "HADR" + ] + }, + "implementation": { + "query": "SELECT ag.group_id AS ag_id, ag.[name] AS ag_name, ar.replica_id, ar.replica_server_name AS ag_replica_server, ar_state.is_local AS is_ag_replica_local, ar.availability_mode, ar.availability_mode_desc, ar.failover_mode, ar.failover_mode_desc, ar_state.[role] AS ag_replica_role, ar_state.role_desc AS ag_replica_role_desc, ar_state.operational_state AS ag_replica_operational_state, ISNULL(ar_state.operational_state_desc, 'UNKNOWN') AS ag_replica_operational_state_desc, ar_state.connected_state AS ag_replica_connected_state, ar_state.synchronization_health AS ag_replica_synchronization_health, ar.secondary_role_allow_connections, ar.secondary_role_allow_connections_desc, avg_state.primary_recovery_health, avg_state.primary_recovery_health_desc, avg_state.synchronization_health, avg_state.synchronization_health_desc, ar.backup_priority, ag.automated_backup_preference, ag.automated_backup_preference_desc, ag.failure_condition_level, ag.health_check_timeout, ar.session_timeout, ar.endpoint_url, CASE WHEN loc_r.replica_id IS NOT NULL THEN 1 ELSE 0 END AS is_on_primary_replica, ag.is_distributed FROM sys.availability_groups AS ag WITH (NOLOCK) INNER JOIN sys.availability_replicas AS ar WITH (NOLOCK) ON ag.group_id = ar.group_id INNER JOIN sys.dm_hadr_availability_replica_states AS ar_state WITH (NOLOCK) ON ar.replica_id = ar_state.replica_id INNER JOIN sys.dm_hadr_availability_group_states AS avg_state WITH (NOLOCK) ON avg_state.group_id = ag.group_id LEFT JOIN sys.dm_hadr_availability_replica_states AS loc_r WITH (NOLOCK) ON loc_r.is_local = 1 AND loc_r.[role] = 1 AND loc_r.group_id = ag.group_id" + } + } + ], + "AGDatabases": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "runFor": { + "feature": [ + "HADR" + ] + }, + "implementation": { + "query": "SELECT d.database_id, DB_NAME(d.database_id) AS databaseName, d.group_id AS ag_id, d.replica_id, d.synchronization_state, d.synchronization_state_desc, d.synchronization_health, d.synchronization_health_desc, d.database_state, d.database_state_desc, rcs.is_database_joined, rcs.is_failover_ready, rcs.is_pending_secondary_suspend FROM sys.dm_hadr_database_replica_states AS d WITH (NOLOCK) INNER JOIN sys.dm_hadr_database_replica_cluster_states AS rcs WITH (NOLOCK) ON rcs.replica_id = d.replica_id AND rcs.group_database_id = d.group_database_id" + } + } + ], + "AGEndpoints": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "runFor": { + "feature": [ + "HADR" + ] + }, + "implementation": { + "query": "SELECT [name] AS endpoint_name, is_encryption_enabled, encryption_algorithm, encryption_algorithm_desc FROM sys.database_mirroring_endpoints" + } + } + ], + "AGListener": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "runFor": { + "feature": [ + "HADR" + ] + }, + "implementation": { + "query": "SELECT ag.group_id, agl.listener_id, dns_name, ip_address, ip_subnet_mask, network_subnet_ip, is_dhcp FROM sys.availability_groups AS ag INNER JOIN sys.availability_group_listeners AS agl ON ag.group_id = agl.group_id INNER JOIN sys.availability_group_listener_ip_addresses AS aglip ON aglip.listener_id = agl.listener_id" + } + } + ], "AzDiskMetadata": [ { "type": "SQL", @@ -12524,33 +13494,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT N'msdb..backupfile' AS table_name, COUNT(*) AS row_count FROM msdb..backupfile UNION SELECT N'msdb..backupmediafamily', COUNT(*) FROM msdb..backupmediafamily UNION SELECT N'msdb..backupmediaset', COUNT(*) FROM msdb..backupmediaset UNION SELECT N'msdb..backupset', COUNT(*) FROM msdb..backupset UNION SELECT N'msdb..restorefile', COUNT(*) FROM msdb..restorefile UNION SELECT N'msdb..restorefilegroup', COUNT(*) FROM msdb..restorefilegroup UNION SELECT N'msdb..restorehistory', COUNT(*) FROM msdb..restorehistory" - } - } - ], - "DatabaseFilesLocation": [ - { - "type": "SQL", - "target": { - "type": "Server", - "platform": "Windows", - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "implementation": { - "query": "SELECT DISTINCT volume_mount_point ,volume_id FROM [sys].[master_files] AS mf INNER JOIN [sys].[databases] AS dbs ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE mf.[type] = ISNULL(@type, mf.[type])" - } - }, - { - "type": "SQL", - "target": { - "type": "Database", - "platform": "Windows", - "engineEdition": "SqlServer, ManagedInstance", - "version": "[11.0,)" - }, - "implementation": { - "query": "SELECT DISTINCT volume_mount_point ,volume_id FROM [sys].[master_files] AS mf INNER JOIN [sys].[databases] AS dbs ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE mf.[type] = ISNULL(@type, mf.[type]) AND dbs.name = @TargetName" + "query": "SELECT N'msdb..backupfile' AS table_name, COUNT(*) AS row_count FROM msdb..backupfile WITH (NOLOCK) UNION SELECT N'msdb..backupmediafamily', COUNT(*) FROM msdb..backupmediafamily WITH (NOLOCK) UNION SELECT N'msdb..backupmediaset', COUNT(*) FROM msdb..backupmediaset WITH (NOLOCK) UNION SELECT N'msdb..backupset', COUNT(*) FROM msdb..backupset WITH (NOLOCK) UNION SELECT N'msdb..restorefile', COUNT(*) FROM msdb..restorefile WITH (NOLOCK) UNION SELECT N'msdb..restorefilegroup', COUNT(*) FROM msdb..restorefilegroup WITH (NOLOCK) UNION SELECT N'msdb..restorehistory', COUNT(*) FROM msdb..restorehistory WITH (NOLOCK)" } } ], @@ -12567,7 +13511,50 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT MIN(compatibility_level) as min_compatibility_level, MAX(compatibility_level) as max_compatibility_level FROM sys.databases" + "query": "SELECT MIN(compatibility_level) as min_compatibility_level, MAX(compatibility_level) as max_compatibility_level FROM sys.databases WITH (NOLOCK)" + } + } + ], + "DatabaseSharedVolumes": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": "Windows", + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "implementation": { + "query": "WITH master_volumes AS ( SELECT DISTINCT mf.database_id ,dbs.[name] AS [database_name] ,CASE WHEN dbs.[name] IN ( 'master' ,'model' ,'msdb' ,'tempdb' ) THEN 1 ELSE dbs.is_distributor END AS is_system_database ,volume_id ,volume_mount_point FROM sys.master_files AS mf WITH (NOLOCK) INNER JOIN sys.databases AS dbs WITH (NOLOCK) ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE ISNULL(volume_id, '') <> '' ) SELECT dbs.* FROM master_volumes AS dbs WITH (NOLOCK) INNER JOIN master_volumes AS db WITH (NOLOCK) ON db.volume_id = dbs.volume_id AND db.database_id = @dbId AND db.database_id <> dbs.database_id AND dbs.is_system_database = ISNULL(@is_system_database, dbs.is_system_database)" + } + }, + { + "type": "SQL", + "target": { + "type": "Database", + "platform": "Windows", + "engineEdition": "SqlServer", + "version": "[11.0,)" + }, + "implementation": { + "query": "WITH master_volumes AS ( SELECT DISTINCT mf.database_id ,dbs.[name] AS [database_name] ,CASE WHEN dbs.[name] IN ( 'master' ,'model' ,'msdb' ,'tempdb' ) THEN 1 ELSE dbs.is_distributor END AS is_system_database ,volume_id ,volume_mount_point FROM sys.master_files AS mf WITH (NOLOCK) INNER JOIN sys.databases AS dbs WITH (NOLOCK) ON mf.database_id = dbs.database_id CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.file_id) WHERE ISNULL(volume_id, '') <> '' ) SELECT dbs.* FROM master_volumes AS dbs WITH (NOLOCK) INNER JOIN master_volumes AS db WITH (NOLOCK) ON db.volume_id = dbs.volume_id AND db.[database_name] = @TargetName AND db.database_id <> dbs.database_id AND dbs.is_system_database = ISNULL(@is_system_database, dbs.is_system_database)" + } + } + ], + "DatabasesState": [ + { + "type": "SQL", + "target": { + "type": "Server", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)" + }, + "implementation": { + "query": "SELECT db.name as DbName, db.source_database_id, db.[state] AS DbState, db.state_desc AS DbStateDesc, db.recovery_model, db.is_in_standby FROM [sys].[databases] (NOLOCK) AS db" } } ], @@ -12654,7 +13641,7 @@ "machineType": "AzureVm" }, "implementation": { - "query": "Resources\n | where type =~ 'Microsoft.Compute/virtualMachines'\n | where properties.vmId =~ @vmId\n | project resourceId = id\n | take 1" + "query": "Resources\r\n | where type =~ 'Microsoft.Compute/virtualMachines'\r\n | where properties.vmId =~ @vmId\r\n | project resourceId = id\r\n | take 1" } } ], @@ -12709,7 +13696,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT SERVERPROPERTY('IsClustered') AS is_clustered_server ,SERVERPROPERTY('ErrorLogFileName') AS error_log_file_path" + "query": "SELECT SERVERPROPERTY('IsClustered') AS is_clustered_server ,SERVERPROPERTY('IsIntegratedSecurityOnly') AS is_integrated_security_only ,SERVERPROPERTY('ErrorLogFileName') AS error_log_file_path ,SERVERPROPERTY('Edition') AS [edition] ,CASE WHEN CAST(SERVERPROPERTY('Edition') AS NVARCHAR(128)) LIKE '%(64-bit)' THEN 64 ELSE 32 END AS [architecture]" } } ], @@ -12741,7 +13728,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT o.[type], o.[type_desc], SUM(total_pages) AS TotalPages, SUM( CASE data_compression_desc WHEN 'NONE' THEN 0 ELSE total_pages END ) AS CompressedPages FROM sys.allocation_units au INNER JOIN sys.[partitions] p ON p.[partition_id] = au.container_id INNER JOIN sys.objects o ON o.[object_id] = p.[object_id] WHERE o.[type] = @type GROUP BY o.[type], o.[type_desc]" + "query": "SELECT o.[type], o.[type_desc], SUM(total_pages) AS TotalPages, SUM( CASE data_compression_desc WHEN 'NONE' THEN 0 ELSE total_pages END ) AS CompressedPages FROM sys.allocation_units AS au WITH (NOLOCK) INNER JOIN sys.[partitions] AS p WITH (NOLOCK) ON p.[partition_id] = au.container_id INNER JOIN sys.objects AS o WITH (NOLOCK) ON o.[object_id] = p.[object_id] WHERE o.[type] = @type GROUP BY o.[type], o.[type_desc]" } } ], @@ -12758,7 +13745,7 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT S.[name] AS [schema_name], P.[name] AS sp_name FROM [master].sys.procedures P INNER JOIN [master].sys.schemas S ON P.[schema_id] = S.[schema_id] WHERE is_ms_shipped = 0 AND is_auto_executed = 1" + "query": "SELECT S.[name] AS [schema_name], P.[name] AS sp_name FROM [master].sys.procedures AS P WITH (NOLOCK) INNER JOIN [master].sys.schemas AS S WITH (NOLOCK) ON P.[schema_id] = S.[schema_id] WHERE is_ms_shipped = 0 AND is_auto_executed = 1" } } ], @@ -12775,7 +13762,42 @@ "version": "[11.0,)" }, "implementation": { - "query": "SELECT sp.principal_id, sp.default_database_name FROM [sys].[server_principals] AS sp INNER JOIN [sys].[server_role_members] AS srm ON sp.principal_id = srm.member_principal_id WHERE sp.is_disabled = 0 AND srm.role_principal_id = 3 AND sp.default_database_name != 'master' COLLATE DATABASE_DEFAULT" + "query": "SELECT sp.principal_id, sp.default_database_name FROM [sys].[server_principals] AS sp WITH (NOLOCK) INNER JOIN [sys].[server_role_members] AS srm WITH (NOLOCK) ON sp.principal_id = srm.member_principal_id WHERE sp.is_disabled = 0 AND srm.role_principal_id = 3 AND sp.default_database_name != 'master' COLLATE DATABASE_DEFAULT" + } + } + ], + "SysFullTextLanguages": [ + { + "type": "SQL", + "target": { + "type": "Server", + "engineEdition": "SqlServer, ManagedInstance", + "platform": [ + "Windows", + "Linux" + ], + "version": "[11.0,)" + }, + "implementation": { + "query": "SELECT [lcid], [name] FROM sys.fulltext_languages WITH(NOLOCK)" + } + } + ], + "TablesInformation": [ + { + "type": "SQL", + "target": { + "type": "Database", + "platform": [ + "Windows", + "Linux" + ], + "engineEdition": "SqlServer, ManagedInstance", + "version": "[11.0,)" + }, + "implementation": { + "useDatabase": true, + "query": "SELECT QUOTENAME(SCHEMA_NAME(so.schema_id)) AS SchemaName, QUOTENAME(so.name) AS TableName, COUNT(*) ColumnCount, idx.IndexCount, idx.FilteredIndexCount FROM sys.objects so (NOLOCK) INNER JOIN sys.columns cols (NOLOCK) ON cols.object_id = so.object_id INNER JOIN ( SELECT si.object_id, CASE MIN(si.index_id) WHEN 0 THEN COUNT(si.index_id) - 1 ELSE COUNT(si.index_id) END AS IndexCount, COUNT(si.filter_definition) AS FilteredIndexCount FROM sys.indexes si (NOLOCK) WHERE si.is_hypothetical = 0 GROUP BY si.object_id ) idx ON idx.object_id = so.object_id LEFT JOIN ( SELECT major_id FROM sys.extended_properties (NOLOCK) WHERE [name] = N'microsoft_database_tools_support' ) X ON X.major_id = so.object_id WHERE so.type in ('U','V') AND so.is_ms_shipped = 0 AND X.major_id IS NULL GROUP BY so.schema_id, so.name, idx.IndexCount, idx.FilteredIndexCount" } } ], @@ -12793,7 +13815,7 @@ }, "implementation": { "useDatabase": true, - "query": "SELECT TOP (CAST(@topN AS INT)) QUOTENAME(OBJECT_SCHEMA_NAME(t.[object_id])) + '.' + QUOTENAME(t.Name) + CASE WHEN i.name IS NULL THEN '' ELSE '.' + QUOTENAME(i.name) END AS IndexName, SUM(a.total_pages) as TotalIndexPages, SUM( CASE p.data_compression_desc WHEN 'NONE' THEN a.total_pages ELSE 0 END ) as TotalIndexUnCompressedPages FROM sys.tables t INNER JOIN sys.[indexes] i ON t.[object_id] = i.[object_id] INNER JOIN sys.[partitions] p ON p.[object_id] = i.[object_id] and i.[index_id] = p.[index_id] INNER JOIN sys.allocation_units a ON p.[partition_id] = a.[container_id] WHERE t.is_ms_shipped = 0 GROUP BY t.name, t.[object_id], i.name ORDER BY TotalIndexUnCompressedPages DESC" + "query": "SELECT TOP (CAST(@topN AS INT)) QUOTENAME(OBJECT_SCHEMA_NAME(t.[object_id])) + '.' + QUOTENAME(t.Name) + CASE WHEN i.name IS NULL THEN '' ELSE '.' + QUOTENAME(i.name) END AS ObjectName, CASE WHEN p.index_id > 0 THEN 1 ELSE 0 END AS ObjectType, SUM(a.total_pages) as TotalIndexPages, SUM( CASE p.data_compression_desc WHEN 'NONE' THEN a.total_pages ELSE 0 END ) as TotalIndexUnCompressedPages FROM sys.[tables] AS t WITH (NOLOCK) INNER JOIN sys.[indexes] AS i WITH (NOLOCK) ON t.[object_id] = i.[object_id] INNER JOIN sys.[partitions] AS p WITH (NOLOCK) ON p.[object_id] = i.[object_id] AND i.[index_id] = p.[index_id] INNER JOIN sys.[allocation_units] AS a WITH (NOLOCK) ON p.[partition_id] = a.[container_id] WHERE t.is_ms_shipped = 0 GROUP BY t.name, t.[object_id], i.name, p.index_id ORDER BY TotalIndexUnCompressedPages DESC" } } ]