{ "metadata": { "kernelspec": { "name": "SQL", "display_name": "SQL", "language": "sql" } }, "language_info": { "name": "sql", "version": "" }, "nbformat_minor": 2, "nbformat": 4, "cells": [ { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "# BPCheck - SQL Best Practices and Performance checks \r\n", "BP Check READ ME - http://aka.ms/BPCheck \r\n", "Checks SQL Server in scope for Performance issues and some of most common skewed Best Practices. \r\n", "Supports SQL Server (starting with SQL Server 2008) and Azure SQL Database Managed Instance. \r\n", "__Note__: Does not support Azure SQL Database single database or Elastic Pool.\r\n" ], "metadata": { "azdata_cell_guid": "ca6b7da5-1f39-4d4b-8198-21184537de37" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "## DISCLAIMER:\r\n", "This code and information are provided \"AS IS\" without warranty of any kind, either expressed or implied.\r\n", "Furthermore, the author or Microsoft shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.\r\n" ], "metadata": { "azdata_cell_guid": "4654ed40-802a-42d5-960e-1d9bea4b00fc" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\t\t\r\n", "## IMPORTANT pre-requisites:\r\n", "- Only a sysadmin/local host admin will be able to perform all checks.\r\n", "- If you want to perform all checks under non-sysadmin credentials, then that login must be:\r\n", "\t- Member of serveradmin server role or have the ALTER SETTINGS server permission; \r\n", "\t- Member of MSDB SQLAgentOperatorRole role, or have SELECT permission on the sysalerts table in MSDB;\r\n", "\t- Granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_enumerrorlogs, xp_fileexist and xp_regenumvalues;\r\n", "\t- Granted EXECUTE permissions on xp_msver;\r\n", "\t- Granted the VIEW SERVER STATE permission;\r\n", "\t- Granted the VIEW DATABASE STATE permission;\r\n", "\t- Granted EXECUTE permissions on xp_cmdshell or a xp_cmdshell proxy account should exist to run checks that access disk or OS security configurations.\r\n", "\t- Member of securityadmin role, or have EXECUTE permissions on sp_readerrorlog. \r\n", " Otherwise some checks will be bypassed and warnings will be shown. \r\n", "- Powershell must be installed to run checks that access disk configurations, as well as allow execution of remote signed or unsigned scripts.\r\n" ], "metadata": { "azdata_cell_guid": "2aae826c-1948-4609-89fc-bb1dfc5488b7" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "## Instructions\r\n", "--\r\n", "You can run any blocks individually **BUT** \r\n", "Ensure that you run the first two blocks first as they will set up some required variables. \r\n", "Some other blocks will require that other blocks have been run first. The Database Information subsection is required to run first for any of the database sections for example. \r\n", "**DO NOT** try to use the *Run Cells* Button to run all of the cells or schedule the Notebook to run as an Agent Job at present. \r\n", " \r\n", "Be Patient - The results in the blocks will sometimes take a moment to appear after the Total exectution time message has appeared. \r\n", " \r\n", "When you have finished, ensure that you run the last block to clear up the temporary tables that have been created.\r\n" ], "metadata": { "azdata_cell_guid": "99d4d49d-5e8d-4ca1-99df-0eff71193883" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "## Pre-requisites section\r\n", "This section will check that all of the required pre-requisites have been met for running the checks and will also set up the variables and tables that are used throughout the Notebook\r\n" ], "metadata": { "azdata_cell_guid": "ce590f52-1720-4ceb-b4f0-439d81695856" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "\tDROP TABLE tempdb.dbo.dbvars\r\n", "END\r\n", "IF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.permstbl\u0027))\r\n", "\t\tBEGIN\r\n", "\t\t\tDROP TABLE tempdb.dbo.permstbl\r\n", "\t\tEND\r\n", "\t\tCREATE TABLE tempdb.dbo.permstbl ([name] sysname);\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.permstbl_msdb\u0027))\r\n", "\tBEGIN\r\n", "\t\tDROP TABLE tempdb.dbo.permstbl_msdb\r\n", "\tEND\r\n", "\tCREATE TABLE tempdb.dbo.permstbl_msdb ([id] tinyint IDENTITY(1,1),[perm] tinyint)\r\n", "IF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 0)\r\n", "BEGIN\r\n", "\tPRINT \u0027WARNING: Only a sysadmin can run ALL the checks\u0027\r\n", "END\r\n", "ELSE\r\n", "BEGIN\r\n", " PRINT \u0027No issues found while checking pre-requisites to run checks: user is sysadmin\u0027\r\n", "END;\r\n", "IF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 0)\r\n", "BEGIN\r\n", "\tDECLARE @pid int, @pname sysname, @msdbpid int\r\n", "\t\r\n", "\tSET @params = \u0027@msdbpid_in int\u0027\r\n", "\tSELECT @pid = principal_id, @pname=name FROM master.sys.server_principals (NOLOCK) WHERE sid = SUSER_SID();\r\n", "\tSELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID();\r\n", "\tSELECT @msdbpid = principal_id FROM msdb.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID();\r\n", "-- Perms 1\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027serveradmin\u0027), 0) <> 1) AND ((SELECT COUNT(l.name)\r\n", "\t\tFROM master.sys.server_permissions p (NOLOCK) INNER JOIN master.sys.server_principals l (NOLOCK)\r\n", "\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\tAND l.is_disabled = 0\r\n", "\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\tAND QUOTENAME(l.name) = QUOTENAME(@pname)) = 0)\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: If not sysadmin, then you must be a member of serveradmin server role or have the ALTER SETTINGS server permission. Exiting...\u0027, 16, 1, N\u0027serveradmin\u0027)\r\n", "\t\tRETURN\r\n", "\tEND\r\n", "\tELSE IF (ISNULL(IS_SRVROLEMEMBER(N\u0027serveradmin\u0027), 0) <> 1) AND ((SELECT COUNT(l.name)\r\n", "\t\tFROM master.sys.server_permissions p (NOLOCK) INNER JOIN sys.server_principals l (NOLOCK)\r\n", "\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\tAND l.is_disabled = 0\r\n", "\t\t\tAND p.permission_name = \u0027VIEW SERVER STATE\u0027\r\n", "\t\t\tAND QUOTENAME(l.name) = QUOTENAME(@pname)) = 0)\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: If not sysadmin, then you must be a member of serveradmin server role or granted the VIEW SERVER STATE permission. Exiting...\u0027, 16, 1, N\u0027serveradmin\u0027)\r\n", "\t\tRETURN\r\n", "\tEND\r\n", " ELSE\r\n", " BEGIN\r\n", " RAISERROR(\u0027INFORMATION: No issues found while checking for sysadmin pre-requisites to run checks\u0027, 10, 1, N\u0027serveradmin\u0027)\r\n", " END;\r\n", "-- Perms 2\r\n", "\tINSERT INTO tempdb.dbo.permstbl\r\n", "\tSELECT a.name\r\n", "\tFROM master.sys.all_objects a (NOLOCK) INNER JOIN master.sys.database_permissions b (NOLOCK) ON a.[OBJECT_ID] = b.major_id\r\n", "\tWHERE a.type IN (\u0027P\u0027, \u0027X\u0027) AND b.grantee_principal_id <>0 \r\n", "\tAND b.grantee_principal_id <> 2\r\n", "\tAND b.grantee_principal_id = @masterpid;\r\n", "\tINSERT INTO tempdb.dbo.permstbl_msdb ([perm])\r\n", "\tEXECUTE sp_executesql N\u0027USE msdb; SELECT COUNT([name]) \r\n", "FROM msdb.sys.sysusers (NOLOCK) WHERE [uid] IN (SELECT [groupuid] \r\n", "\tFROM msdb.sys.sysmembers (NOLOCK) WHERE [memberuid] = @msdbpid_in) \r\n", "AND [name] = \u0027\u0027SQLAgentOperatorRole\u0027\u0027\u0027, @params, @msdbpid_in = @msdbpid;\r\n", "\tINSERT INTO tempdb.dbo.permstbl_msdb ([perm])\r\n", "\tEXECUTE sp_executesql N\u0027USE msdb; SELECT COUNT(dp.grantee_principal_id)\r\n", "FROM msdb.sys.tables AS tbl (NOLOCK)\r\n", "INNER JOIN msdb.sys.database_permissions AS dp (NOLOCK) ON dp.major_id=tbl.object_id AND dp.class=1\r\n", "INNER JOIN msdb.sys.database_principals AS grantor_principal (NOLOCK) ON grantor_principal.principal_id = dp.grantor_principal_id\r\n", "INNER JOIN msdb.sys.database_principals AS grantee_principal (NOLOCK) ON grantee_principal.principal_id = dp.grantee_principal_id\r\n", "WHERE dp.state = \u0027\u0027G\u0027\u0027\r\n", "\tAND dp.grantee_principal_id = @msdbpid_in\r\n", "\tAND dp.type = \u0027\u0027SL\u0027\u0027\u0027, @params, @msdbpid_in = @msdbpid;\r\n", "\tIF (SELECT [perm] FROM tempdb.dbo.permstbl_msdb WHERE [id] = 1) = 0 AND (SELECT [perm] FROM tempdb.dbo.permstbl_msdb WHERE [id] = 2) = 0\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: If not sysadmin, then you must be a member of MSDB SQLAgentOperatorRole role, or have SELECT permission on the sysalerts table in MSDB to run full scope of checks\u0027, 16, 1, N\u0027msdbperms\u0027)\r\n", "\t--RETURN\r\n", " END\r\n", "\tELSE IF (ISNULL(IS_SRVROLEMEMBER(N\u0027securityadmin\u0027), 0) <> 1) AND ((SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_enumerrorlogs\u0027) = 0 OR (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027sp_readerrorlog\u0027) = 0 OR (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_readerrorlog\u0027) = 0)\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: If not sysadmin, then you must be a member of the securityadmin server role, or have EXECUTE permission on the following extended sprocs to run full scope of checks: xp_enumerrorlogs, xp_readerrorlog, sp_readerrorlog\u0027, 16, 1, N\u0027secperms\u0027)\r\n", "\t--RETURN\r\n", "\tEND\r\n", "\tELSE IF (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_cmdshell\u0027) = 0 OR (SELECT COUNT(credential_id) FROM master.sys.credentials WHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) = 0\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: If not sysadmin, then you must be granted EXECUTE permissions on xp_cmdshell and a xp_cmdshell proxy account should exist to run full scope of checks\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t--RETURN\r\n", "\tEND\r\n", "\tELSE IF (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_fileexist\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027sp_OAGetErrorInfo\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027sp_OACreate\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027sp_OADestroy\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_regenumvalues\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_regread\u0027) = 0 OR \r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_instance_regread\u0027) = 0 OR\r\n", "\t\t(SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_servicecontrol\u0027) = 0 \r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: Must be a granted EXECUTE permissions on the following extended sprocs to run full scope of checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_fileexist, xp_regread, xp_instance_regread, xp_servicecontrol and xp_regenumvalues\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\tEND\r\n", "\tELSE IF (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_msver\u0027) = 0 AND @sqlmajorver < 11\r\n", "\tBEGIN\r\n", "\t\tRAISERROR(\u0027WARNING: Must be granted EXECUTE permissions on xp_msver to run full scope of checks\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\tEND\r\n", " ELSE\r\n", " BEGIN\r\n", " RAISERROR(\u0027INFORMATION: No issues found while checking for granular pre-requisites to run checks\u0027, 10, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", " END\r\n", "END;\r\n" ], "metadata": { "azdata_cell_guid": "9204d919-d773-4b09-a408-ce8483e95381", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", " OR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1 \r\n", " AND (SELECT COUNT(credential_id) FROM sys.credentials WHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", " AND (SELECT COUNT(l.name)\r\n", " FROM sys.server_permissions p JOIN sys.server_principals l \r\n", " ON p.grantee_principal_id = l.principal_id\r\n", " AND p.class = 100 -- Server\r\n", " AND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", " AND l.is_disabled = 0\r\n", " AND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", " AND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission\r\n", " OR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1 \r\n", " AND ((SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", " (SELECT COUNT([name]) FROM tempdb.dbo.permstbl WHERE [name] = \u0027xp_cmdshell\u0027) > 0)))\r\n", "BEGIN\r\n", " DECLARE @pstbl_avail TABLE ([KeyExist] int)\r\n", " BEGIN TRY\r\n", " INSERT INTO @pstbl_avail\r\n", " EXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, N\u0027SOFTWARE\\Microsoft\\PowerShell\\1\u0027 -- check if Powershell is installed\r\n", " END TRY\r\n", " BEGIN CATCH\r\n", " SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", " SELECT @ErrorMessage = \u0027Could not determine if Powershell is installed - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", " RAISERROR (@ErrorMessage, 16, 1);\r\n", " END CATCH\r\n", " SELECT @sao = CAST([value] AS smallint) FROM sys.configurations (NOLOCK) WHERE [name] = \u0027show advanced options\u0027\r\n", " SELECT @xcmd = CAST([value] AS smallint) FROM sys.configurations (NOLOCK) WHERE [name] = \u0027xp_cmdshell\u0027\r\n", " SELECT @ole = CAST([value] AS smallint) FROM sys.configurations (NOLOCK) WHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", " RAISERROR (\u0027Configuration options set for Powershell enablement verification\u0027, 10, 1) WITH NOWAIT\r\n", " IF @sao = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027show advanced options\u0027, 1; RECONFIGURE WITH OVERRIDE;\r\n", " END\r\n", " IF @xcmd = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027xp_cmdshell\u0027, 1; RECONFIGURE WITH OVERRIDE;\r\n", " END\r\n", " IF @ole = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027Ole Automation Procedures\u0027, 1; RECONFIGURE WITH OVERRIDE;\r\n", " END\r\n", " \r\n", " IF (SELECT [KeyExist] FROM @pstbl_avail) = 1\r\n", " BEGIN\r\n", " DECLARE @psavail_output TABLE ([PS_OUTPUT] VARCHAR(2048));\r\n", " INSERT INTO @psavail_output\r\n", " EXEC master.dbo.xp_cmdshell N\u0027%WINDIR%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"Get-ExecutionPolicy\"\u0027\r\n", " \r\n", " SELECT @psavail = [PS_OUTPUT] FROM @psavail_output WHERE [PS_OUTPUT] IS NOT NULL;\r\n", " END\r\n", " ELSE\r\n", " BEGIN\r\n", " RAISERROR (\u0027WARNING: Powershell is not installed. Install WinRM to proceed with PS based checks\u0027,16,1);\r\n", " END\r\n", " \r\n", " IF (@psavail IS NOT NULL AND @psavail NOT IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", " RAISERROR (\u0027WARNING: Execution of Powershell scripts is disabled on this system.\r\n", "To change the execution policy, type the following command in Powershell console: Set-ExecutionPolicy RemoteSigned\r\n", "The Set-ExecutionPolicy cmdlet enables you to determine which Windows PowerShell scripts (if any) will be allowed to run on your computer. Windows PowerShell has four different execution policies:\r\n", "Restricted - No scripts can be run. Windows PowerShell can be used only in interactive mode.\r\n", "AllSigned - Only scripts signed by a trusted publisher can be run.\r\n", "RemoteSigned - Downloaded scripts must be signed by a trusted publisher before they can be run.\r\n", "Unrestricted - No restrictions; all Windows PowerShell scripts can be run; REQUIRED by BP Check.\u0027,16,1);\r\n", " IF (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", " BEGIN\r\n", " RAISERROR (\u0027INFORMATION: Powershell is installed and enabled for script execution\u0027, 10, 1) WITH NOWAIT\r\n", " \r\n", " DECLARE @psver_output TABLE ([PS_OUTPUT] VARCHAR(1024));\r\n", " INSERT INTO @psver_output\r\n", " EXEC master.dbo.xp_cmdshell N\u0027%WINDIR%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"Get-Host | Format-Table -Property Version\"\u0027\r\n", " \r\n", " -- Gets PS version, as commands issued to PS v1 do not support -File\r\n", " SELECT @psver = ISNULL(LEFT([PS_OUTPUT],1),2) FROM @psver_output WHERE [PS_OUTPUT] IS NOT NULL AND ISNUMERIC(LEFT([PS_OUTPUT],1)) = 1;\r\n", " \r\n", " SET @ErrorMessage = \u0027INFORMATION: Installed Powershell is version \u0027 + CONVERT(CHAR(1), @psver) + \u0027\u0027\r\n", " PRINT @ErrorMessage\r\n", " END;\r\n", " \r\n", " IF @xcmd = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027xp_cmdshell\u0027, 0; RECONFIGURE WITH OVERRIDE;\r\n", " END\r\n", " IF @ole = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027Ole Automation Procedures\u0027, 0; RECONFIGURE WITH OVERRIDE;\r\n", " END\r\n", " IF @sao = 0\r\n", " BEGIN\r\n", " EXEC sp_configure \u0027show advanced options\u0027, 0; RECONFIGURE WITH OVERRIDE;\r\n", " END;\r\n", "END\r\n", "ELSE\r\n", "BEGIN\r\n", " RAISERROR (\u0027WARNING: Missing permissions for Powershell enablement verification\u0027, 16, 1) WITH NOWAIT\r\n", "END;\r\n", "INSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027psavail\u0027, @psavail )\r\n" ], "metadata": { "azdata_cell_guid": "c6309d91-c0d8-4439-9ff4-5abe51dbc2b6", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "## Information section\r\n", "This section contains information about the instance\r\n", "---\r\n", "---\r\n", "\r\n" ], "metadata": { "azdata_cell_guid": "70263e8f-5085-439a-ab66-811ce369799e" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Uptime subsection\r\n", "The time since the instance last started\r\n" ], "metadata": { "azdata_cell_guid": "84d43a9a-2398-4845-9844-24a1ba8ac8fa" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027Starting Information section\u0027, 10, 1) WITH NOWAIT\r\n", "\tRAISERROR (N\u0027|-Starting Uptime\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @sqlmajorver < 10\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @UpTimeOUT = DATEDIFF(mi, login_time, GETDATE()), @StartDateOUT = login_time FROM master..sysprocesses (NOLOCK) WHERE spid = 1\u0027;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @UpTimeOUT = DATEDIFF(mi,sqlserver_start_time,GETDATE()), @StartDateOUT = sqlserver_start_time FROM sys.dm_os_sys_info (NOLOCK)\u0027;\r\n", "\tEND\r\n", "\tSET @params = N\u0027@UpTimeOUT VARCHAR(12) OUTPUT, @StartDateOUT DATETIME OUTPUT\u0027;\r\n", "\tEXECUTE sp_executesql @sqlcmd, @params, @UpTimeOUT=@UpTime OUTPUT, @StartDateOUT=@StartDate OUTPUT;\r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Uptime\u0027 AS [Information], GETDATE() AS [Current_Time], @StartDate AS Last_Startup, CONVERT(VARCHAR(4),@UpTime/60/24) + \u0027d \u0027 + CONVERT(VARCHAR(4),@UpTime/60%24) + \u0027hr \u0027 + CONVERT(VARCHAR(4),@UpTime%60) + \u0027min\u0027 AS Uptime\r\n" ], "metadata": { "azdata_cell_guid": "d3e3f292-c7db-47fb-8e39-b5e4031fbe86", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### OS Version and Architecture subsection\r\n" ], "metadata": { "azdata_cell_guid": "43c2cb20-600a-4471-a776-cf28f52a83ba" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Windows Version and Architecture\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (@sqlmajorver >= 11 AND @sqlmajorver < 14) OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @ostypeOUT = \u0027\u0027Windows\u0027\u0027, @osdistroOUT = \u0027\u0027Windows\u0027\u0027, @osverOUT = CASE WHEN windows_release IN (\u0027\u00276.3\u0027\u0027,\u0027\u002710.0\u0027\u0027) AND (@@VERSION LIKE \u0027\u0027%Build 10586%\u0027\u0027 OR @@VERSION LIKE \u0027\u0027%Build 14393%\u0027\u0027) THEN \u0027\u002710.0\u0027\u0027 ELSE windows_release END, @osspOUT = windows_service_pack_level, @archOUT = CASE WHEN @@VERSION LIKE \u0027\u0027%%\u0027\u0027 THEN 64 WHEN @@VERSION LIKE \u0027\u0027%%\u0027\u0027 THEN 128 ELSE 32 END FROM sys.dm_os_windows_info (NOLOCK)\u0027;\r\n", "\t\tSET @params = N\u0027@osverOUT VARCHAR(5) OUTPUT, @ostypeOUT VARCHAR(10) OUTPUT, @osdistroOUT VARCHAR(20) OUTPUT, @osspOUT VARCHAR(25) OUTPUT, @archOUT smallint OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @osverOUT=@osver OUTPUT, @ostypeOUT=@ostype OUTPUT, @osdistroOUT=@osdistro OUTPUT, @osspOUT=@ossp OUTPUT, @archOUT=@arch OUTPUT;\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver >= 14\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @ostypeOUT = host_platform, @osdistroOUT = host_distribution, @osverOUT = CASE WHEN host_platform = \u0027\u0027Windows\u0027\u0027 AND host_release IN (\u0027\u00276.3\u0027\u0027,\u0027\u002710.0\u0027\u0027) THEN \u0027\u002710.0\u0027\u0027 ELSE host_release END, @osspOUT = host_service_pack_level, @archOUT = CASE WHEN @@VERSION LIKE \u0027\u0027%%\u0027\u0027 THEN 64 ELSE 32 END FROM sys.dm_os_host_info (NOLOCK)\u0027;\r\n", "\t\tSET @params = N\u0027@osverOUT VARCHAR(5) OUTPUT, @ostypeOUT VARCHAR(10) OUTPUT, @osdistroOUT VARCHAR(20) OUTPUT, @osspOUT VARCHAR(25) OUTPUT, @archOUT smallint OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @osverOUT=@osver OUTPUT, @ostypeOUT=@ostype OUTPUT, @osdistroOUT=@osdistro OUTPUT, @osspOUT=@ossp OUTPUT, @archOUT=@arch OUTPUT;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t\tDECLARE @str VARCHAR(500), @str2 VARCHAR(500), @str3 VARCHAR(500)\r\n", "\t\tDECLARE @sysinfo TABLE (id int,\r\n", "\t\t\t[Name] NVARCHAR(256),\r\n", "\t\t\tInternal_Value bigint,\r\n", "\t\t\tCharacter_Value NVARCHAR(256));\r\n", "\t\t\t\r\n", "\t\tINSERT INTO @sysinfo\r\n", "\t\tEXEC xp_msver;\r\n", "\t\t\r\n", "\t\tSELECT @osver = LEFT(Character_Value, CHARINDEX(\u0027 \u0027, Character_Value)-1)\r\n", "\t-- 5.2 is WS2003; 6.0 is WS2008; 6.1 is WS2008R2; 6.2 is WS2012, 6.3 is WS2012R2, 6.3 (14396) is WS2016\r\n", "\t\tFROM @sysinfo\r\n", "\t\tWHERE [Name] LIKE \u0027WindowsVersion%\u0027;\r\n", "\t\t\r\n", "\t\tSELECT @arch = CASE WHEN RTRIM(Character_Value) LIKE \u0027%x64%\u0027 OR RTRIM(Character_Value) LIKE \u0027%AMD64%\u0027 THEN 64\r\n", "\t\t\tWHEN RTRIM(Character_Value) LIKE \u0027%x86%\u0027 OR RTRIM(Character_Value) LIKE \u0027%32%\u0027 THEN 32\r\n", "\t\t\tWHEN RTRIM(Character_Value) LIKE \u0027%IA64%\u0027 THEN 128 END\r\n", "\t\tFROM @sysinfo\r\n", "\t\tWHERE [Name] LIKE \u0027Platform%\u0027;\r\n", "\t\t\r\n", "\t\tSET @str = (SELECT @@VERSION)\r\n", "\t\tSELECT @str2 = RIGHT(@str, LEN(@str)-CHARINDEX(\u0027Windows\u0027,@str) + 1)\r\n", "\t\tSELECT @str3 = RIGHT(@str2, LEN(@str2)-CHARINDEX(\u0027: \u0027,@str2))\r\n", "\t\tSELECT @ossp = LTRIM(LEFT(@str3, CHARINDEX(\u0027)\u0027,@str3) -1))\r\n", "\t\tSET @ostype = \u0027Windows\u0027\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Windows Version and Architecture subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND;\r\n", "\tDECLARE @machineinfo TABLE ([Value] NVARCHAR(256),\r\n", "\t\t[Data] NVARCHAR(256))\r\n", "\tIF @ostype = \u0027Windows\u0027\r\n", "BEGIN\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027SystemManufacturer\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027SystemProductName\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027SystemFamily\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027BIOSVendor\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027BIOSVersion\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\BIOS\u0027,\u0027BIOSReleaseDate\u0027;\r\n", "\t\tINSERT INTO @machineinfo\r\n", "\t\tEXEC xp_instance_regread \u0027HKEY_LOCAL_MACHINE\u0027,\u0027HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\u0027,\u0027ProcessorNameString\u0027;\r\n", "\t\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027ostype\u0027,\u0027Windows\u0027)\r\n", "\t\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027osver\u0027, @osver )\r\n", "\tEND;\r\n", "\tSELECT @SystemManufacturer = [Data]\r\n", "\tFROM @machineinfo\r\n", "\tWHERE [Value] = \u0027SystemManufacturer\u0027;\r\n", "\tSELECT @BIOSVendor = [Data]\r\n", "\tFROM @machineinfo\r\n", "\tWHERE [Value] = \u0027BIOSVendor\u0027;\r\n", "\tSELECT @Processor_Name = [Data]\r\n", "\tFROM @machineinfo\r\n", "\tWHERE [Value] = \u0027ProcessorNameString\u0027;\r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Machine\u0027 AS [Information],\r\n", "\t\tCASE @osver WHEN \u00275.2\u0027 THEN \u0027XP/WS2003\u0027\r\n", "\t\tWHEN \u00276.0\u0027 THEN \u0027Vista/WS2008\u0027\r\n", "\t\tWHEN \u00276.1\u0027 THEN \u0027W7/WS2008R2\u0027\r\n", "\t\tWHEN \u00276.2\u0027 THEN \u0027W8/WS2012\u0027\r\n", "\t\tWHEN \u00276.3\u0027 THEN \u0027W8.1/WS2012R2\u0027\r\n", "\t\tWHEN \u002710.0\u0027 THEN \u0027W10/WS2016\u0027\r\n", "\t\tELSE @ostype + \u0027 \u0027 + @osdistro\r\n", "\tEND AS [OS_Version],\r\n", "\t\tCASE WHEN @ostype = \u0027Windows\u0027 THEN @ossp ELSE @osver END AS [Service_Pack_Level],\r\n", "\t\t@arch AS [Architecture],\r\n", "\t\tSERVERPROPERTY(\u0027MachineName\u0027) AS [Machine_Name],\r\n", "\t\tSERVERPROPERTY(\u0027ComputerNamePhysicalNetBIOS\u0027) AS [NetBIOS_Name],\r\n", "\t\t@SystemManufacturer AS [System_Manufacturer],\r\n", "\t\t(SELECT [Data]\r\n", "\t\tFROM @machineinfo\r\n", "\t\tWHERE [Value] = \u0027SystemFamily\u0027) AS [System_Family],\r\n", "\t\t(SELECT [Data]\r\n", "\t\tFROM @machineinfo\r\n", "\t\tWHERE [Value] = \u0027SystemProductName\u0027) AS [System_ProductName],\r\n", "\t\t@BIOSVendor AS [BIOS_Vendor],\r\n", "\t\t(SELECT [Data]\r\n", "\t\tFROM @machineinfo\r\n", "\t\tWHERE [Value] = \u0027BIOSVersion\u0027) AS [BIOS_Version],\r\n", "\t\t(SELECT [Data]\r\n", "\t\tFROM @machineinfo\r\n", "\t\tWHERE [Value] = \u0027BIOSReleaseDate\u0027) AS [BIOS_Release_Date],\r\n", "\t\t@Processor_Name AS [Processor_Name];\r\n" ], "metadata": { "azdata_cell_guid": "8d5a689a-57e1-48b4-90ab-fd4cd77fae04", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Disk space subsection\r\n" ], "metadata": { "azdata_cell_guid": "99935d15-9bb9-4f9c-8d10-67ba71093653" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 10 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027|-Starting Disk space\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tSELECT DISTINCT \u0027Information\u0027 AS [Category], \u0027Disk_Space\u0027 AS [Information], vs.logical_volume_name,\r\n", "\t\t\tvs.volume_mount_point, vs.file_system_type, CONVERT(int,vs.total_bytes/1048576.0) AS TotalSpace_MB,\r\n", "\t\t\tCONVERT(int,vs.available_bytes/1048576.0) AS FreeSpace_MB, vs.is_compressed\r\n", "\t\tFROM sys.master_files mf\r\n", "\tCROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.[file_id]) vs\r\n", "\t\tORDER BY FreeSpace_MB ASC\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "e10705ad-7d81-4d8d-b527-34ea43b973f1", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### HA Information subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "39ba0613-2028-4462-b239-84f1616c547b" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting HA Information\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @clustered = 1\r\n", "BEGIN\r\n", "\t\tIF @sqlmajorver < 11\r\n", "\t\tBEGIN\r\n", "\t\t\tEXEC (\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Cluster\u0027\u0027 AS [Information], NodeName AS node_name FROM sys.dm_os_cluster_nodes (NOLOCK)\u0027)\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\tEXEC (\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Cluster\u0027\u0027 AS [Information], NodeName AS node_name, status_description, is_current_owner FROM sys.dm_os_cluster_nodes (NOLOCK)\u0027)\r\n", "\t\tEND\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Cluster\u0027 AS [Information], DriveName AS cluster_shared_drives\r\n", "\t\tFROM sys.dm_io_cluster_shared_drives (NOLOCK)\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Cluster\u0027 AS [Information], \u0027NOT_CLUSTERED\u0027 AS [Status]\r\n", "\tEND;\r\n", "\tIF @sqlmajorver > 10\r\n", "BEGIN\r\n", "\t\tDECLARE @HadrManagerStatus tinyint\r\n", "\t\tSELECT @HadrManagerStatus = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027HadrManagerStatus\u0027)) END;\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_AG\u0027 AS [Information],\r\n", "\t\t\tCASE @IsHadrEnabled WHEN 0 THEN \u0027Disabled\u0027\r\n", "\t\t\tWHEN 1 THEN \u0027Enabled\u0027 END AS [AlwaysOn_Availability_Groups],\r\n", "\t\t\tCASE WHEN @IsHadrEnabled = 1 THEN\r\n", "\t\t\tCASE @HadrManagerStatus WHEN 0 THEN \u0027[Not started, pending communication]\u0027\r\n", "\t\t\t\tWHEN 1 THEN \u0027[Started and running]\u0027\r\n", "\t\t\t\tWHEN 2 THEN \u0027[Not started and failed]\u0027\r\n", "\t\t\tEND\r\n", "\t\tEND AS [Status];\r\n", "\t\tIF @IsHadrEnabled = 1\r\n", "\tBEGIN\r\n", "\t\t\tIF EXISTS (SELECT 1\r\n", "\t\t\tFROM sys.dm_hadr_cluster) \r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_Cluster\u0027 AS [Information], cluster_name, quorum_type_desc, quorum_state_desc\r\n", "\t\t\tFROM sys.dm_hadr_cluster;\r\n", "\t\t\tIF EXISTS (SELECT 1\r\n", "\t\t\tFROM sys.dm_hadr_cluster_members) \r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_Cluster_Members\u0027 AS [Information], member_name, member_type_desc, member_state_desc, number_of_quorum_votes\r\n", "\t\t\tFROM sys.dm_hadr_cluster_members;\r\n", "\t\t\tIF EXISTS (SELECT 1\r\n", "\t\t\tFROM sys.dm_hadr_cluster_networks) \r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_Cluster_Networks\u0027 AS [Information], member_name, network_subnet_ip, network_subnet_ipv4_mask, is_public, is_ipv4\r\n", "\t\t\tFROM sys.dm_hadr_cluster_networks;\r\n", "\t\tEND;\r\n", "\t\tIF @ptochecks = 1 AND @IsHadrEnabled = 1\r\n", "\tBEGIN\r\n", "\t\t-- Note: If low_water_mark_for_ghosts number is not increasing over time, it implies that ghost cleanup might not happen.\r\n", "\t\t\tSET @sqlcmd = \u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027AlwaysOn_Replicas\u0027\u0027 AS [Information], database_id, group_id, replica_id, group_database_id, is_local, synchronization_state_desc, \r\n", "\tis_commit_participant, synchronization_health_desc, database_state_desc, is_suspended, suspend_reason_desc, last_sent_time, last_received_time, last_hardened_time, \r\n", "\tlast_redone_time, log_send_queue_size, log_send_rate, redo_queue_size, redo_rate, filestream_send_rate, last_commit_time, \r\n", "\tlow_water_mark_for_ghosts\u0027 + CASE WHEN @sqlmajorver > 12 THEN \u0027, secondary_lag_seconds\u0027 ELSE \u0027\u0027 END + \u0027 \r\n", "FROM sys.dm_hadr_database_replica_states\u0027\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_Replica_Cluster\u0027 AS [Information], replica_id, group_database_id, database_name, is_failover_ready, is_pending_secondary_suspend,\r\n", "\t\t\t\tis_database_joined, recovery_lsn, truncation_lsn\r\n", "\t\t\tFROM sys.dm_hadr_database_replica_cluster_states;\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "8513ce8a-59d7-4adb-a19c-829c3727a8a6", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Linked servers info subsection\r\n" ], "metadata": { "azdata_cell_guid": "bdb28a6c-1c10-4655-905b-215785df9d83" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Linked servers info\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM sys.servers AS s INNER JOIN sys.linked_logins AS l (NOLOCK) ON s.server_id = l.server_id LEFT OUTER JOIN sys.server_principals AS p (NOLOCK) ON p.principal_id = l.local_principal_id\r\n", "\tWHERE s.is_linked = 1) > 0\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Linked_servers\u0027\u0027 AS [Information], s.name, s.product, \r\n", "\ts.provider, s.data_source, s.location, s.provider_string, s.catalog, s.connect_timeout, \r\n", "\ts.query_timeout, s.is_linked, s.is_remote_login_enabled, s.is_rpc_out_enabled, \r\n", "\ts.is_data_access_enabled, s.is_collation_compatible, s.uses_remote_collation, s.collation_name, \r\n", "\ts.lazy_schema_validation, s.is_system, s.is_publisher, s.is_subscriber, s.is_distributor, \r\n", "\ts.is_nonsql_subscriber\u0027 + CASE WHEN @sqlmajorver > 9 THEN \u0027, s.is_remote_proc_transaction_promotion_enabled\u0027 ELSE \u0027\u0027 END + \u0027,\r\n", "\ts.modify_date, CASE WHEN l.local_principal_id = 0 THEN \u0027\u0027local or wildcard\u0027\u0027 ELSE p.name END AS [local_principal], \r\n", "\tCASE WHEN l.uses_self_credential = 0 THEN \u0027\u0027use own credentials\u0027\u0027 ELSE \u0027\u0027use supplied username and pwd\u0027\u0027 END AS uses_self_credential, \r\n", "\tl.remote_name, l.modify_date AS [linked_login_modify_date]\r\n", "FROM sys.servers AS s (NOLOCK)\r\n", "INNER JOIN sys.linked_logins AS l (NOLOCK) ON s.server_id = l.server_id\r\n", "LEFT OUTER JOIN sys.server_principals AS p (NOLOCK) ON p.principal_id = l.local_principal_id\r\n", "WHERE s.is_linked = 1\u0027\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Linked_servers\u0027 AS [Information], \u0027[None]\u0027 AS [Status]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "0d0d45e0-5bb4-47ca-99c3-6231af474dae", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Instance info subsection\r\n" ], "metadata": { "azdata_cell_guid": "5574aae1-58c3-4759-b52d-555aaef8638e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Instance info\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild < 2500)\r\n", "BEGIN\r\n", "\t\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1) OR ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regread\u0027) = 1)\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tSELECT @RegKey = CASE WHEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027InstanceName\u0027)) IS NULL THEN N\u0027Software\\Microsoft\\MSSQLServer\\MSSQLServer\\SuperSocketNetLib\\Tcp\u0027\r\n", "\t\t\t\tELSE N\u0027Software\\Microsoft\\Microsoft SQL Server\\\u0027 + CAST(SERVERPROPERTY(\u0027InstanceName\u0027) AS NVARCHAR(128)) + N\u0027\\MSSQLServer\\SuperSocketNetLib\\Tcp\u0027 END\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @RegKey, N\u0027TcpPort\u0027, @port OUTPUT, NO_OUTPUT\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Instance info subsection - Error raised in TRY block 1. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Missing permissions for full \"Instance info\" checks. Bypassing TCP port check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t\t/*\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @portOUT = MAX(CONVERT(VARCHAR(15),value_data)) FROM sys.dm_server_registry WHERE registry_key LIKE \u0027\u0027%MSSQLServer\\SuperSocketNetLib\\Tcp\\%\u0027\u0027 AND value_name LIKE N\u0027\u0027%TcpPort%\u0027\u0027 AND CONVERT(float,value_data) > 0;\u0027;\r\n", "\t\tSET @params = N\u0027@portOUT VARCHAR(15) OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @portOUT = @port OUTPUT;\r\n", "\t\tIF @port IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @portOUT = CONVERT(VARCHAR(15),value_data) FROM sys.dm_server_registry WHERE registry_key LIKE \u0027\u0027%MSSQLServer\\SuperSocketNetLib\\Tcp\\%\u0027\u0027 AND value_name LIKE N\u0027\u0027%TcpDynamicPort%\u0027\u0027 AND CONVERT(float,value_data) > 0;\u0027;\r\n", "\t\t\tSET @params = N\u0027@portOUT VARCHAR(15) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @portOUT = @port OUTPUT;\r\n", "\t\tEND\r\n", "\t\t*/\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @portOUT = MAX(CONVERT(VARCHAR(15),port)) FROM sys.dm_tcp_listener_states WHERE is_ipv4 = 1 AND [type] = 0 AND ip_address <> \u0027\u0027127.0.0.1\u0027\u0027;\u0027;\r\n", "\t\tSET @params = N\u0027@portOUT VARCHAR(15) OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @portOUT = @port OUTPUT;\r\n", "\t\tIF @port IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @portOUT = MAX(CONVERT(VARCHAR(15),port)) FROM sys.dm_tcp_listener_states WHERE is_ipv4 = 0 AND [type] = 0 AND ip_address <> \u0027\u0027127.0.0.1\u0027\u0027;\u0027;\r\n", "\t\t\tSET @params = N\u0027@portOUT VARCHAR(15) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @portOUT = @port OUTPUT;\r\n", "\t\tEND\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Instance info subsection - Error raised in TRY block 2. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1) OR ((SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_instance_regread\u0027) = 1)\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027, N\u0027SOFTWARE\\Microsoft\\MSSQLServer\\Replication\u0027, N\u0027IsInstalled\u0027, @replication OUTPUT, NO_OUTPUT\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Instance info subsection - Error raised in TRY block 3. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Missing permissions for full \"Instance info\" checks. Bypassing replication check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND\r\n", "\tSELECT @cpucount = COUNT(cpu_id)\r\n", "\tFROM sys.dm_os_schedulers\r\n", "\tWHERE scheduler_id < 255 AND parent_node_id < 64\r\n", "\tSELECT @numa = COUNT(DISTINCT parent_node_id)\r\n", "\tFROM sys.dm_os_schedulers\r\n", "\tWHERE scheduler_id < 255 AND parent_node_id < 64;\r\n", "\t;WITH\r\n", "\t\tbits\r\n", "\t\tAS\r\n", "\t\t(\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT 7 AS N, 128 AS E\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 6, 64\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 5, 32\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 4, 16\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 3, 8\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 2, 4\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 1, 2\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 0, 1\r\n", "\t\t),\r\n", "\t\tbytes\r\n", "\t\tAS\r\n", "\t\t(\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT 1 M\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 2\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 3\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 4\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 5\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 6\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 7\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 8\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT 9\r\n", "\t\t)\r\n", "-- CPU Affinity is shown highest to lowest CPU ID\r\n", "\tSELECT @affinitymask = CASE WHEN [value] = 0 THEN REPLICATE(\u00271\u0027, @cpucount)\r\n", "\tELSE RIGHT((SELECT ((CONVERT(tinyint, SUBSTRING(CONVERT(binary(9), [value]), M, 1)) \u0026 E) / E) AS [text()]\r\n", "\t\tFROM bits CROSS JOIN bytes\r\n", "\t\tORDER BY M, N DESC\r\n", "\t\tFOR XML PATH(\u0027\u0027)), @cpucount) END\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027affinity mask\u0027;\r\n", "\tIF @cpucount > 32\r\n", "BEGIN\r\n", "\t\t;WITH\r\n", "\t\t\tbits\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT 7 AS N, 128 AS E\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 6, 64\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 5, 32\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 4, 16\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 3, 8\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 2, 4\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 1, 2\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 0, 1\r\n", "\t\t\t),\r\n", "\t\t\tbytes\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT 1 M\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 2\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 3\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 4\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 5\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 6\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 7\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 8\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT 9\r\n", "\t\t\t)\r\n", "\t-- CPU Affinity is shown highest to lowest CPU ID\r\n", "\t\tSELECT @affinity64mask = CASE WHEN [value] = 0 THEN REPLICATE(\u00271\u0027, @cpucount)\r\n", "\t\tELSE RIGHT((SELECT ((CONVERT(tinyint, SUBSTRING(CONVERT(binary(9), [value]), M, 1)) \u0026 E) / E) AS [text()]\r\n", "\t\t\tFROM bits CROSS JOIN bytes\r\n", "\t\t\tORDER BY M, N DESC\r\n", "\t\t\tFOR XML PATH(\u0027\u0027)), @cpucount) END\r\n", "\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\tWHERE name = \u0027affinity64 mask\u0027;\r\n", "\tEND;\r\n", "\t/*\r\n", "IF @cpucount > 32\r\n", "SELECT @cpuover32 = ABS(LEN(@affinity64mask) - (@cpucount-32))\r\n", "SELECT @cpuaffin = CASE WHEN @cpucount > 32 THEN REVERSE(LEFT(REVERSE(@affinity64mask),@cpuover32)) + RIGHT(@affinitymask,32) ELSE RIGHT(@affinitymask,@cpucount) END\r\n", "*/\r\n", "\tSELECT @cpuaffin = CASE WHEN @cpucount > 32 THEN @affinity64mask ELSE @affinitymask END\r\n", "\tSET @cpuaffin_fixed = @cpuaffin\r\n", "\tIF @numa > 1\r\n", "BEGIN\r\n", "\t-- format binary mask by node for better reading\r\n", "\t\tSET @i = CEILING(@cpucount*1.00/@numa) + 1\r\n", "\t\tWHILE @i < @cpucount + @numa\r\n", "\tBEGIN\r\n", "\t\t\tIF (@cpucount + @numa) - @i >= CEILING(@cpucount*1.00/@numa)\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @cpuaffin_fixed = STUFF(@cpuaffin_fixed, @i, 1, \u0027_\u0027 + SUBSTRING(@cpuaffin_fixed, @i, 1))\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @cpuaffin_fixed = STUFF(@cpuaffin_fixed, @i, CEILING(@cpucount*1.00/@numa), SUBSTRING(@cpuaffin_fixed, @i, CEILING(@cpucount*1.00/@numa)))\r\n", "\t\t\tEND\r\n", "\t\t\tSET @i = @i + CEILING(@cpucount*1.00/@numa) + 1\r\n", "\t\tEND\r\n", "\tEND\r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Instance\u0027 AS [Information],\r\n", "\t\t(CASE WHEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027InstanceName\u0027)) IS NULL THEN \u0027DEFAULT_INSTANCE\u0027\r\n", "\t\tELSE CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027InstanceName\u0027)) END) AS Instance_Name,\r\n", "\t\t(CASE WHEN SERVERPROPERTY(\u0027IsClustered\u0027) = 1 THEN \u0027CLUSTERED\u0027 \r\n", "\t\tWHEN SERVERPROPERTY(\u0027IsClustered\u0027) = 0 THEN \u0027NOT_CLUSTERED\u0027\r\n", "\t\tELSE \u0027INVALID INPUT/ERROR\u0027 END) AS Failover_Clustered,\r\n", "\t\t/*The version of SQL Server instance in the form: major.minor.build*/\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductVersion\u0027)) AS Product_Version,\r\n", "\t\t/*Level of the version of SQL Server Instance*/\r\n", "\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlminorver >= 6020) OR (@sqlmajorver = 12 AND @sqlminorver BETWEEN 2556 AND 2569) OR (@sqlmajorver = 12 AND @sqlminorver >= 4427) OR @sqlmajorver >= 13 THEN \r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductBuildType\u0027))\r\n", "\tELSE \u0027NA\u0027 END AS Product_Build_Type,\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductLevel\u0027)) AS Product_Level,\r\n", "\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlminorver >= 6020) OR (@sqlmajorver = 12 AND @sqlminorver BETWEEN 2556 AND 2569) OR (@sqlmajorver = 12 AND @sqlminorver >= 4427) OR @sqlmajorver >= 13 THEN \r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductUpdateLevel\u0027))\r\n", "\tELSE \u0027NA\u0027 END AS Product_Update_Level,\r\n", "\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlminorver >= 6020) OR (@sqlmajorver = 12 AND @sqlminorver BETWEEN 2556 AND 2569) OR (@sqlmajorver = 12 AND @sqlminorver >= 4427) OR @sqlmajorver >= 13 THEN \r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductUpdateReference\u0027))\r\n", "\tELSE \u0027NA\u0027 END AS Product_Update_Ref_KB,\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027Edition\u0027)) AS Edition,\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)) AS Machine_Name,\r\n", "\t\tRTRIM(@port) AS TCP_Port,\r\n", "\t\t@@SERVICENAME AS Service_Name,\r\n", "\t\t/*To identify which sqlservr.exe belongs to this instance*/\r\n", "\t\tSERVERPROPERTY(\u0027ProcessID\u0027) AS Process_ID,\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ServerName\u0027)) AS Server_Name,\r\n", "\t\t@cpuaffin_fixed AS Affinity_Mask_Bitmask,\r\n", "\t\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027Collation\u0027)) AS [Server_Collation],\r\n", "\t\t(CASE WHEN @replication = 1 THEN \u0027Installed\u0027 \r\n", "\t\tWHEN @replication = 0 THEN \u0027Not_Installed\u0027 \r\n", "\t\tELSE \u0027INVALID INPUT/ERROR\u0027 END) AS Replication_Components_Installation,\r\n", "\t\t(CASE WHEN SERVERPROPERTY(\u0027IsFullTextInstalled\u0027) = 1 THEN \u0027Installed\u0027 \r\n", "\t\tWHEN SERVERPROPERTY(\u0027IsFulltextInstalled\u0027) = 0 THEN \u0027Not_Installed\u0027 \r\n", "\t\tELSE \u0027INVALID INPUT/ERROR\u0027 END) AS Full_Text_Installation,\r\n", "\t\t(CASE WHEN SERVERPROPERTY(\u0027IsIntegratedSecurityOnly\u0027) = 1 THEN \u0027Integrated_Security\u0027 \r\n", "\t\tWHEN SERVERPROPERTY(\u0027IsIntegratedSecurityOnly\u0027) = 0 THEN \u0027SQL_Server_Security\u0027 \r\n", "\t\tELSE \u0027INVALID INPUT/ERROR\u0027 END) AS [Security],\r\n", "\t\t(CASE WHEN SERVERPROPERTY(\u0027IsSingleUser\u0027) = 1 THEN \u0027Single_User\u0027 \r\n", "\t\tWHEN SERVERPROPERTY(\u0027IsSingleUser\u0027) = 0\tTHEN \u0027Multi_User\u0027 \r\n", "\t\tELSE \u0027INVALID INPUT/ERROR\u0027 END) AS [Single_User],\r\n", "\t\t(CASE WHEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027LicenseType\u0027)) = \u0027PER_SEAT\u0027 THEN \u0027Per_Seat_Mode\u0027 \r\n", "\t\tWHEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027LicenseType\u0027)) = \u0027PER_PROCESSOR\u0027 THEN \u0027Per_Processor_Mode\u0027 \r\n", "\t\tELSE \u0027Disabled\u0027 END) AS License_Type, -- From SQL Server 2008R2 always returns DISABLED.\r\n", "\t\tCONVERT(NVARCHAR(128), SERVERPROPERTY(\u0027BuildClrVersion\u0027)) AS CLR_Version,\r\n", "\t\tCASE WHEN @sqlmajorver >= 10 THEN \r\n", "\t\tCASE WHEN SERVERPROPERTY(\u0027FilestreamConfiguredLevel\u0027) = 0 THEN \u0027Disabled\u0027\r\n", "\t\t\tWHEN SERVERPROPERTY(\u0027FilestreamConfiguredLevel\u0027) = 1 THEN \u0027Enabled_for_TSQL\u0027\r\n", "\t\t\tELSE \u0027Enabled for TSQL and Win32\u0027 END\r\n", "\tELSE \u0027Not compatible\u0027 END AS Filestream_Configured_Level,\r\n", "\t\tCASE WHEN @sqlmajorver >= 10 THEN \r\n", "\t\tCASE WHEN SERVERPROPERTY(\u0027FilestreamEffectiveLevel\u0027) = 0 THEN \u0027Disabled\u0027\r\n", "\t\t\tWHEN SERVERPROPERTY(\u0027FilestreamEffectiveLevel\u0027) = 1 THEN \u0027Enabled_for_TSQL\u0027\r\n", "\t\t\tELSE \u0027Enabled for TSQL and Win32\u0027 END\r\n", "\tELSE \u0027Not compatible\u0027 END AS Filestream_Effective_Level,\r\n", "\t\tCASE WHEN @sqlmajorver >= 10 THEN \r\n", "\t\tSERVERPROPERTY(\u0027FilestreamShareName\u0027)\r\n", "\tELSE \u0027Not compatible\u0027 END AS Filestream_Share_Name,\r\n", "\t\tCASE WHEN @sqlmajorver >= 12 THEN \r\n", "\t\tSERVERPROPERTY(\u0027IsXTPSupported\u0027)\r\n", "\tELSE \u0027Not compatible\u0027 END AS XTP_Compatible,\r\n", "\t\tCASE WHEN @sqlmajorver >= 13 THEN \r\n", "\t\tSERVERPROPERTY(\u0027IsPolybaseInstalled\u0027)\r\n", "\tELSE \u0027Not compatible\u0027 END AS Polybase_Installed,\r\n", "\t\tCASE WHEN @sqlmajorver >= 13 THEN \r\n", "\t\tSERVERPROPERTY(\u0027IsAdvancedAnalyticsInstalled\u0027)\r\n", "\tELSE \u0027Not compatible\u0027 END AS R_Services_Installed;\r\n" ], "metadata": { "azdata_cell_guid": "a96c629d-5982-4d6b-bf0e-1b40605d571b", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Buffer Pool Extension info subsection\r\n" ], "metadata": { "azdata_cell_guid": "bc06ef19-8d3e-4c3f-a745-50971fb3c6fe" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Buffer Pool Extension info\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @sqlmajorver > 11\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027BP_Extension\u0027 AS [Information],\r\n", "\t\t\tCASE WHEN state = 0 THEN \u0027BP_Extension_Disabled\u0027 \r\n", "\t\t\tWHEN state = 1 THEN \u0027BP_Extension_is_Disabling\u0027\r\n", "\t\t\tWHEN state = 3 THEN \u0027BP_Extension_is_Enabling\u0027\r\n", "\t\t\tWHEN state = 5 THEN \u0027BP_Extension_Enabled\u0027\r\n", "\t\tEND AS state,\r\n", "\t\t\t[path], current_size_in_kb\r\n", "\t\tFROM sys.dm_os_buffer_pool_extension_configuration\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027BP_Extension\u0027 AS [Information], \u0027[NA]\u0027 AS state\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "83f12e87-55aa-488b-b55d-d7d0eeae8767", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Resource Governor info subsection\r\n" ], "metadata": { "azdata_cell_guid": "d0cfa239-25fe-4732-af51-a5e67d96e43f" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Resource Governor info\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @sqlmajorver > 9\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027RG_Classifier_Function\u0027 AS [Information], CASE WHEN classifier_function_id = 0 THEN \u0027Default_Configuration\u0027 ELSE OBJECT_SCHEMA_NAME(classifier_function_id) + \u0027.\u0027 + OBJECT_NAME(classifier_function_id) END AS classifier_function, is_reconfiguration_pending\r\n", "\t\tFROM sys.dm_resource_governor_configuration\r\n", "\t\tSET @sqlcmd = \u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027RG_Resource_Pool\u0027\u0027 AS [Information], rp.pool_id, name, statistics_start_time, total_cpu_usage_ms, cache_memory_kb, compile_memory_kb, \r\n", "\tused_memgrant_kb, total_memgrant_count, total_memgrant_timeout_count, active_memgrant_count, active_memgrant_kb, memgrant_waiter_count, max_memory_kb, used_memory_kb, target_memory_kb, \r\n", "\tout_of_memory_count, min_cpu_percent, max_cpu_percent, min_memory_percent, max_memory_percent\u0027 + CASE WHEN @sqlmajorver > 10 THEN \u0027, cap_cpu_percent, rpa.processor_group, rpa.scheduler_mask\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "FROM sys.dm_resource_governor_resource_pools rp\u0027 + CASE WHEN @sqlmajorver > 10 THEN \u0027 LEFT JOIN sys.dm_resource_governor_resource_pool_affinity rpa ON rp.pool_id = rpa.pool_id\u0027 ELSE \u0027\u0027 END\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tSET @sqlcmd = \u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027RG_Workload_Groups\u0027\u0027 AS [Information], group_id, name, pool_id, statistics_start_time, total_request_count, total_queued_request_count, \r\n", "\tactive_request_count, queued_request_count, total_cpu_limit_violation_count, total_cpu_usage_ms, max_request_cpu_time_ms, blocked_task_count, total_lock_wait_count, \r\n", "\ttotal_lock_wait_time_ms, total_query_optimization_count, total_suboptimal_plan_generation_count, total_reduced_memgrant_count, max_request_grant_memory_kb, \r\n", "\tactive_parallel_thread_count, importance, request_max_memory_grant_percent, request_max_cpu_time_sec, request_memory_grant_timeout_sec, \r\n", "\tgroup_max_requests, max_dop\u0027 + CASE WHEN @sqlmajorver > 10 THEN \u0027, effective_max_dop\u0027 ELSE \u0027\u0027 END + \u0027 \r\n", "FROM sys.dm_resource_governor_workload_groups\u0027\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "2045af0b-945c-4cf6-af22-067d66212e16", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Logon triggers subsection\r\n" ], "metadata": { "azdata_cell_guid": "2d2e7ea5-d1ba-42e6-9a73-e02b037b71b9" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Logon triggers\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT([name])\r\n", "\tFROM sys.server_triggers\r\n", "\tWHERE is_disabled = 0 AND is_ms_shipped = 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Logon_Triggers\u0027 AS [Information], name AS [Trigger_Name], type_desc AS [Trigger_Type], create_date, modify_date\r\n", "\t\tFROM sys.server_triggers\r\n", "\t\tWHERE is_disabled = 0 AND is_ms_shipped = 0\r\n", "\t\tORDER BY name;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Logon_Triggers\u0027 AS [Information], \u0027[NA]\u0027 AS [Comment]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "f2fff855-7b1c-4c49-ac18-a526d8997a3f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Database Information subsection\r\n", "- This block is *required* to be run before later blocks which gather information about the databases on the instance\r\n", "- You can set the @DbScope variable below to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n" ], "metadata": { "azdata_cell_guid": "54cddcd0-0379-46b6-9fc3-c820339b8b87" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Database Information\u0027, 10, 1) WITH NOWAIT\r\n", "\tRAISERROR (N\u0027 |-Building DB list\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @curdbname NVARCHAR(1000), @curdbid int, @currole tinyint, @cursecondary_role_allow_connections tinyint, @state tinyint\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs0\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs0;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs0\u0027))\r\n", "CREATE TABLE tempdb.dbo.tmpdbs0\r\n", "\t(\r\n", "\t\tid int IDENTITY(1,1),\r\n", "\t\t[dbid] int,\r\n", "\t\t[dbname] NVARCHAR(1000),\r\n", "\t\t[compatibility_level] tinyint,\r\n", "\t\tis_read_only bit,\r\n", "\t\t[state] tinyint,\r\n", "\t\tis_distributor bit,\r\n", "\t\t[role] tinyint,\r\n", "\t\t[secondary_role_allow_connections] tinyint,\r\n", "\t\tis_database_joined bit,\r\n", "\t\tis_failover_ready bit,\r\n", "\t\tis_query_store_on bit,\r\n", "\t\tisdone bit\r\n", "\t);\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpdbfiledetail\u0027))\r\n", "DROP TABLE #tmpdbfiledetail;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpdbfiledetail\u0027))\r\n", "CREATE TABLE #tmpdbfiledetail\r\n", "\t(\r\n", "\t\t[database_id] [int] NOT NULL,\r\n", "\t\t[file_id] int,\r\n", "\t\t[type_desc] NVARCHAR(60),\r\n", "\t\t[data_space_id] int,\r\n", "\t\t[name] sysname,\r\n", "\t\t[physical_name] NVARCHAR(260),\r\n", "\t\t[state_desc] NVARCHAR(60),\r\n", "\t\t[size] bigint,\r\n", "\t\t[max_size] bigint,\r\n", "\t\t[is_percent_growth] bit,\r\n", "\t\t[growth] int,\r\n", "\t\t[is_media_read_only] bit,\r\n", "\t\t[is_read_only] bit,\r\n", "\t\t[is_sparse] bit,\r\n", "\t\t[is_name_reserved] bit\r\n", "\t)\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tmpdbsizes\u0027))\r\n", "DROP TABLE ##tmpdbsizes;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tmpdbsizes\u0027))\r\n", "CREATE TABLE ##tmpdbsizes\r\n", "\t(\r\n", "\t\t[database_id] [int] NOT NULL,\r\n", "\t\t[size] bigint,\r\n", "\t\t[type_desc] NVARCHAR(60)\r\n", "\t)\r\n", "\tIF @sqlmajorver < 11\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT database_id, name, [compatibility_level], is_read_only, [state], is_distributor, 1, 1, 0, 0 FROM master.sys.databases (NOLOCK)\u0027\r\n", "\t\tINSERT INTO tempdb.dbo.tmpdbs0\r\n", "\t\t\t([dbid], [dbname], [compatibility_level], is_read_only, [state], is_distributor, [role], [secondary_role_allow_connections], is_query_store_on, [isdone])\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND;\r\n", "\tIF @sqlmajorver IN (11,12)\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT sd.database_id, sd.name, sd.[compatibility_level], sd.is_read_only, sd.[state], sd.is_distributor, MIN(COALESCE(ars.[role],1)) AS [role], ar.secondary_role_allow_connections, rcs.is_database_joined, rcs.is_failover_ready, 0, 0 \r\n", "\tFROM master.sys.databases (NOLOCK) sd\r\n", "\t\tLEFT JOIN sys.dm_hadr_database_replica_states (NOLOCK) d ON sd.database_id = d.database_id\r\n", "\t\tLEFT JOIN sys.availability_replicas ar (NOLOCK) ON d.group_id = ar.group_id AND d.replica_id = ar.replica_id\r\n", "\t\tLEFT JOIN sys.dm_hadr_availability_replica_states (NOLOCK) ars ON d.group_id = ars.group_id AND d.replica_id = ars.replica_id\r\n", "\t\tLEFT JOIN sys.dm_hadr_database_replica_cluster_states (NOLOCK) rcs ON rcs.database_name = sd.name AND rcs.replica_id = ar.replica_id\r\n", "\tGROUP BY sd.database_id, sd.name, sd.is_read_only, sd.[state], sd.is_distributor, ar.secondary_role_allow_connections, sd.[compatibility_level], rcs.is_database_joined, rcs.is_failover_ready;\u0027\r\n", "\t\tINSERT INTO tempdb.dbo.tmpdbs0\r\n", "\t\t\t([dbid], [dbname], [compatibility_level], is_read_only, [state], is_distributor, [role], [secondary_role_allow_connections], is_database_joined, is_failover_ready, is_query_store_on, [isdone])\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND;\r\n", "\tIF @sqlmajorver > 12\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT sd.database_id, sd.name, sd.[compatibility_level], sd.is_read_only, sd.[state], sd.is_distributor, MIN(COALESCE(ars.[role],1)) AS [role], ar.secondary_role_allow_connections, rcs.is_database_joined, rcs.is_failover_ready, sd.is_query_store_on, 0 \r\n", "\tFROM master.sys.databases (NOLOCK) sd\r\n", "\t\tLEFT JOIN sys.dm_hadr_database_replica_states (NOLOCK) d ON sd.database_id = d.database_id\r\n", "\t\tLEFT JOIN sys.availability_replicas ar (NOLOCK) ON d.group_id = ar.group_id AND d.replica_id = ar.replica_id\r\n", "\t\tLEFT JOIN sys.dm_hadr_availability_replica_states (NOLOCK) ars ON d.group_id = ars.group_id AND d.replica_id = ars.replica_id\r\n", "\t\tLEFT JOIN sys.dm_hadr_database_replica_cluster_states (NOLOCK) rcs ON rcs.database_name = sd.name AND rcs.replica_id = ar.replica_id\r\n", "\tGROUP BY sd.database_id, sd.name, sd.is_read_only, sd.[state], sd.is_distributor, ar.secondary_role_allow_connections, sd.[compatibility_level], rcs.is_database_joined, rcs.is_failover_ready, sd.is_query_store_on;\u0027\r\n", "\t\tINSERT INTO tempdb.dbo.tmpdbs0\r\n", "\t\t\t([dbid], [dbname], [compatibility_level], is_read_only, [state], is_distributor, [role], [secondary_role_allow_connections], is_database_joined, is_failover_ready, is_query_store_on, [isdone])\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND;\r\n", "\t/* Validate if database scope is set */\r\n", "\tIF @dbScope IS NOT NULL AND ISNUMERIC(@dbScope) <> 1 AND @dbScope NOT LIKE \u0027%,%\u0027\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027ERROR: Invalid parameter. Valid input consists of database IDs. If more than one ID is specified, the values must be comma separated.\u0027, 16, 42) WITH NOWAIT;\r\n", "\t\tRETURN\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027 |-Applying specific database scope list, if any\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @dbScope IS NOT NULL\r\n", "BEGIN\r\n", "\t\tSELECT @sqlcmd = \u0027DELETE FROM tempdb.dbo.tmpdbs0 WHERE [dbid] > 4 AND [dbid] NOT IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND;\r\n", "\t/* Populate data file info*/\r\n", "\tWHILE (SELECT COUNT(id)\r\n", "\tFROM tempdb.dbo.tmpdbs0\r\n", "\tWHERE isdone = 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT TOP 1\r\n", "\t\t\t@curdbname = [dbname], @curdbid = [dbid], @currole = [role], @state = [state], @cursecondary_role_allow_connections = secondary_role_allow_connections\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0\r\n", "\t\tIF (@currole = 2 AND @cursecondary_role_allow_connections = 0) OR @state <> 0\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = \u0027SELECT [database_id], [file_id], type_desc, data_space_id, name, physical_name, state_desc, size, max_size, is_percent_growth,growth, is_media_read_only, is_read_only, is_sparse, is_name_reserved\r\n", "FROM sys.master_files (NOLOCK) WHERE [database_id] = \u0027 + CONVERT(VARCHAR(10), @curdbid)\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@curdbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(10), @curdbid) + \u0027 AS [database_id], [file_id], type_desc, data_space_id, name, physical_name, state_desc, size, max_size, is_percent_growth,growth, is_media_read_only, is_read_only, is_sparse, is_name_reserved\r\n", "FROM sys.database_files (NOLOCK)\u0027\r\n", "\t\tEND\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #tmpdbfiledetail\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Database Information subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [dbid] = @curdbid\r\n", "\tEND;\r\n", "\tBEGIN TRY\r\n", "\tINSERT INTO ##tmpdbsizes\r\n", "\t\t([database_id], [size], [type_desc])\r\n", "\tSELECT [database_id], SUM([size]) AS [size], [type_desc]\r\n", "\tFROM #tmpdbfiledetail\r\n", "\tWHERE [type_desc] <> \u0027LOG\u0027\r\n", "\tGROUP BY [database_id], [type_desc]\r\n", "END TRY\r\n", "BEGIN CATCH\r\n", "\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\tSELECT @ErrorMessage = \u0027Database Information subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "END CATCH\r\n", "\tIF @sqlmajorver < 11\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Databases\u0027\u0027 AS [Information],\r\n", "\tdb.[name] AS [Database_Name], SUSER_SNAME(db.owner_sid) AS [Owner_Name], db.[database_id], \r\n", "\tdb.recovery_model_desc AS [Recovery_Model], db.create_date, db.log_reuse_wait_desc AS [Log_Reuse_Wait_Description], \r\n", "\t(dbsize.[size]*8)/1024 AS [Data_Size_MB], ISNULL((dbfssize.[size]*8)/1024,0) AS [Filestream_Size_MB], \r\n", "\tls.cntr_value/1024 AS [Log_Size_MB], lu.cntr_value/1024 AS [Log_Used_MB],\r\n", "\tCAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log_Used_pct], \r\n", "\tdb.[compatibility_level] AS [Compatibility_Level], db.collation_name AS [DB_Collation], \r\n", "\tdb.page_verify_option_desc AS [Page_Verify_Option], db.is_auto_create_stats_on, db.is_auto_update_stats_on,\r\n", "\tdb.is_auto_update_stats_async_on, db.is_parameterization_forced, \r\n", "\tdb.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on,\r\n", "\tdb.is_read_only, db.is_auto_close_on, db.is_auto_shrink_on, \u0027\u0027NA\u0027\u0027 AS [is_indirect_checkpoint_on], \r\n", "\tdb.is_trustworthy_on, db.is_db_chaining_on, db.is_parameterization_forced\r\n", "FROM master.sys.databases AS db (NOLOCK)\r\n", "INNER JOIN ##tmpdbsizes AS dbsize (NOLOCK) ON db.database_id = dbsize.database_id\r\n", "INNER JOIN sys.dm_os_performance_counters AS lu (NOLOCK) ON db.name = lu.instance_name\r\n", "INNER JOIN sys.dm_os_performance_counters AS ls (NOLOCK) ON db.name = ls.instance_name\r\n", "LEFT JOIN ##tmpdbsizes AS dbfssize (NOLOCK) ON db.database_id = dbfssize.database_id AND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "WHERE dbsize.[type_desc] = \u0027\u0027ROWS\u0027\u0027\r\n", "\tAND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "\tAND lu.counter_name LIKE N\u0027\u0027Log File(s) Used Size (KB)%\u0027\u0027 \r\n", "\tAND ls.counter_name LIKE N\u0027\u0027Log File(s) Size (KB)%\u0027\u0027\r\n", "\tAND ls.cntr_value > 0 AND ls.cntr_value > 0\u0027 + CASE WHEN @dbScope IS NOT NULL THEN CHAR(10) + \u0027 AND db.[database_id] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY [Database_Name]\t\r\n", "OPTION (RECOMPILE)\u0027\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver = 11\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Databases\u0027\u0027 AS [Information],\r\n", "\tdb.[name] AS [Database_Name], SUSER_SNAME(db.owner_sid) AS [Owner_Name], db.[database_id], \r\n", "\tdb.recovery_model_desc AS [Recovery_Model], db.create_date, db.log_reuse_wait_desc AS [Log_Reuse_Wait_Description], \r\n", "\t(dbsize.[size]*8)/1024 AS [Data_Size_MB], ISNULL((dbfssize.[size]*8)/1024,0) AS [Filestream_Size_MB], \r\n", "\tls.cntr_value/1024 AS [Log_Size_MB], lu.cntr_value/1024 AS [Log_Used_MB],\r\n", "\tCAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log_Used_pct], \r\n", "\tdb.[compatibility_level] AS [Compatibility_Level], db.collation_name AS [DB_Collation], \r\n", "\tdb.page_verify_option_desc AS [Page_Verify_Option], db.is_auto_create_stats_on, db.is_auto_update_stats_on,\r\n", "\tdb.is_auto_update_stats_async_on, db.is_parameterization_forced, \r\n", "\tdb.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on,\r\n", "\tdb.is_read_only, db.is_auto_close_on, db.is_auto_shrink_on, \r\n", "\tCASE WHEN db.target_recovery_time_in_seconds > 0 THEN 1 ELSE 0 END AS is_indirect_checkpoint_on,\r\n", "\tdb.target_recovery_time_in_seconds, db.is_encrypted, db.is_trustworthy_on, db.is_db_chaining_on, db.is_parameterization_forced\r\n", "FROM master.sys.databases AS db (NOLOCK)\r\n", "INNER JOIN ##tmpdbsizes AS dbsize (NOLOCK) ON db.database_id = dbsize.database_id\r\n", "INNER JOIN sys.dm_os_performance_counters AS lu (NOLOCK) ON db.name = lu.instance_name\r\n", "INNER JOIN sys.dm_os_performance_counters AS ls (NOLOCK) ON db.name = ls.instance_name\r\n", "LEFT JOIN ##tmpdbsizes AS dbfssize (NOLOCK) ON db.database_id = dbfssize.database_id AND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "WHERE dbsize.[type_desc] = \u0027\u0027ROWS\u0027\u0027\r\n", "\tAND lu.counter_name LIKE N\u0027\u0027Log File(s) Used Size (KB)%\u0027\u0027 \r\n", "\tAND ls.counter_name LIKE N\u0027\u0027Log File(s) Size (KB)%\u0027\u0027\r\n", "\tAND ls.cntr_value > 0 AND ls.cntr_value > 0\u0027 + CASE WHEN @dbScope IS NOT NULL THEN CHAR(10) + \u0027 AND db.[database_id] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY [Database_Name]\t\r\n", "OPTION (RECOMPILE)\u0027\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver = 12\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Databases\u0027\u0027 AS [Information],\r\n", "\tdb.[name] AS [Database_Name], SUSER_SNAME(db.owner_sid) AS [Owner_Name], db.[database_id], \r\n", "\tdb.recovery_model_desc AS [Recovery_Model], db.create_date, db.log_reuse_wait_desc AS [Log_Reuse_Wait_Description], \r\n", "\t(dbsize.[size]*8)/1024 AS [Data_Size_MB], ISNULL((dbfssize.[size]*8)/1024,0) AS [Filestream_Size_MB], \r\n", "\tls.cntr_value/1024 AS [Log_Size_MB], lu.cntr_value/1024 AS [Log_Used_MB],\r\n", "\tCAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log_Used_pct], \r\n", "\tdb.[compatibility_level] AS [Compatibility_Level], db.collation_name AS [DB_Collation], \r\n", "\tdb.page_verify_option_desc AS [Page_Verify_Option], db.is_auto_create_stats_on, db.is_auto_create_stats_incremental_on,\r\n", "\tdb.is_auto_update_stats_on, db.is_auto_update_stats_async_on, db.delayed_durability_desc AS [delayed_durability_status], \r\n", "\tdb.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on,\r\n", "\tdb.is_read_only, db.is_auto_close_on, db.is_auto_shrink_on,\r\n", "\tCASE WHEN db.target_recovery_time_in_seconds > 0 THEN 1 ELSE 0 END AS is_indirect_checkpoint_on,\r\n", "\tdb.target_recovery_time_in_seconds, db.is_encrypted, db.is_trustworthy_on, db.is_db_chaining_on, db.is_parameterization_forced\r\n", "FROM master.sys.databases AS db (NOLOCK)\r\n", "INNER JOIN ##tmpdbsizes AS dbsize (NOLOCK) ON db.database_id = dbsize.database_id\r\n", "INNER JOIN sys.dm_os_performance_counters AS lu (NOLOCK) ON db.name = lu.instance_name\r\n", "INNER JOIN sys.dm_os_performance_counters AS ls (NOLOCK) ON db.name = ls.instance_name\r\n", "LEFT JOIN ##tmpdbsizes AS dbfssize (NOLOCK) ON db.database_id = dbfssize.database_id AND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "WHERE dbsize.[type_desc] = \u0027\u0027ROWS\u0027\u0027\r\n", "\tAND lu.counter_name LIKE N\u0027\u0027Log File(s) Used Size (KB)%\u0027\u0027 \r\n", "\tAND ls.counter_name LIKE N\u0027\u0027Log File(s) Size (KB)%\u0027\u0027\r\n", "\tAND ls.cntr_value > 0 AND ls.cntr_value > 0\u0027 + CASE WHEN @dbScope IS NOT NULL THEN CHAR(10) + \u0027 AND db.[database_id] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY [Database_Name]\t\r\n", "OPTION (RECOMPILE)\u0027\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver >= 13\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Databases\u0027\u0027 AS [Information],\r\n", "\tdb.[name] AS [Database_Name], SUSER_SNAME(db.owner_sid) AS [Owner_Name], db.[database_id], \r\n", "\tdb.recovery_model_desc AS [Recovery_Model], db.create_date, db.log_reuse_wait_desc AS [Log_Reuse_Wait_Description], \r\n", "\t(dbsize.[size]*8)/1024 AS [Data_Size_MB], ISNULL((dbfssize.[size]*8)/1024,0) AS [Filestream_Size_MB], \r\n", "\tls.cntr_value/1024 AS [Log_Size_MB], lu.cntr_value/1024 AS [Log_Used_MB],\r\n", "\tCAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log_Used_pct], \r\n", "\tdb.[compatibility_level] AS [Compatibility_Level], db.collation_name AS [DB_Collation], \r\n", "\tdb.page_verify_option_desc AS [Page_Verify_Option], db.is_auto_create_stats_on, db.is_auto_create_stats_incremental_on,\r\n", "\tdb.is_auto_update_stats_on, db.is_auto_update_stats_async_on, db.delayed_durability_desc AS [delayed_durability_status], \r\n", "\tdb.is_query_store_on, db.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on,\r\n", "\tdb.is_read_only, db.is_auto_close_on, db.is_auto_shrink_on, \r\n", "\tCASE WHEN db.target_recovery_time_in_seconds > 0 THEN 1 ELSE 0 END AS is_indirect_checkpoint_on,\r\n", "\tdb.target_recovery_time_in_seconds, db.is_encrypted, db.is_trustworthy_on, db.is_db_chaining_on, db.is_parameterization_forced, \r\n", "\tdb.is_memory_optimized_elevate_to_snapshot_on, db.is_remote_data_archive_enabled, db.is_mixed_page_allocation_on\r\n", "FROM master.sys.databases AS db (NOLOCK)\r\n", "INNER JOIN sys.dm_os_performance_counters AS lu (NOLOCK) ON db.name = lu.instance_name\r\n", "INNER JOIN sys.dm_os_performance_counters AS ls (NOLOCK) ON db.name = ls.instance_name\r\n", "INNER JOIN ##tmpdbsizes AS dbsize (NOLOCK) ON db.database_id = dbsize.database_id\r\n", "LEFT JOIN ##tmpdbsizes AS dbfssize (NOLOCK) ON db.database_id = dbfssize.database_id AND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "WHERE dbsize.[type_desc] = \u0027\u0027ROWS\u0027\u0027\r\n", "\tAND lu.counter_name LIKE N\u0027\u0027Log File(s) Used Size (KB)%\u0027\u0027 \r\n", "\tAND ls.counter_name LIKE N\u0027\u0027Log File(s) Size (KB)%\u0027\u0027\r\n", "\tAND ls.cntr_value > 0 AND ls.cntr_value > 0\u0027 + CASE WHEN @dbScope IS NOT NULL THEN CHAR(10) + \u0027 AND db.[database_id] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY [Database_Name]\t\r\n", "OPTION (RECOMPILE)\u0027\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver >= 14\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Databases\u0027\u0027 AS [Information],\r\n", "\tdb.[name] AS [Database_Name], SUSER_SNAME(db.owner_sid) AS [Owner_Name], db.[database_id], \r\n", "\tdb.recovery_model_desc AS [Recovery_Model], db.create_date, db.log_reuse_wait_desc AS [Log_Reuse_Wait_Description], \r\n", "\t(dbsize.[size]*8)/1024 AS [Data_Size_MB], ISNULL((dbfssize.[size]*8)/1024,0) AS [Filestream_Size_MB], \r\n", "\tls.cntr_value/1024 AS [Log_Size_MB], lu.cntr_value/1024 AS [Log_Used_MB],\r\n", "\tCAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log_Used_pct],\r\n", "\tCASE WHEN ssu.reserved_space_kb>0 THEN ssu.reserved_space_kb/1024 ELSE 0 END AS [Version_Store_Size_MB],\r\n", "\tdb.[compatibility_level] AS [Compatibility_Level], db.collation_name AS [DB_Collation], \r\n", "\tdb.page_verify_option_desc AS [Page_Verify_Option], db.is_auto_create_stats_on, db.is_auto_create_stats_incremental_on,\r\n", "\tdb.is_auto_update_stats_on, db.is_auto_update_stats_async_on, db.delayed_durability_desc AS [delayed_durability_status], \r\n", "\tdb.is_query_store_on, db.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on,\r\n", "\tdb.is_read_only, db.is_auto_close_on, db.is_auto_shrink_on, \r\n", "\tCASE WHEN db.target_recovery_time_in_seconds > 0 THEN 1 ELSE 0 END AS is_indirect_checkpoint_on,\r\n", "\tdb.target_recovery_time_in_seconds, db.is_encrypted, db.is_trustworthy_on, db.is_db_chaining_on, db.is_parameterization_forced, \r\n", "\tdb.is_memory_optimized_elevate_to_snapshot_on, db.is_remote_data_archive_enabled, db.is_mixed_page_allocation_on\r\n", "FROM master.sys.databases AS db (NOLOCK)\r\n", "INNER JOIN ##tmpdbsizes AS dbsize (NOLOCK) ON db.database_id = dbsize.database_id\r\n", "INNER JOIN sys.dm_os_performance_counters AS lu (NOLOCK) ON db.name = lu.instance_name\r\n", "INNER JOIN sys.dm_os_performance_counters AS ls (NOLOCK) ON db.name = ls.instance_name\r\n", "LEFT JOIN ##tmpdbsizes AS dbfssize (NOLOCK) ON db.database_id = dbfssize.database_id AND dbfssize.[type_desc] = \u0027\u0027FILESTREAM\u0027\u0027\r\n", "LEFT JOIN sys.dm_tran_version_store_space_usage AS ssu (NOLOCK) ON db.database_id = ssu.database_id\r\n", "WHERE dbsize.[type_desc] = \u0027\u0027ROWS\u0027\u0027\r\n", "\tAND lu.counter_name LIKE N\u0027\u0027Log File(s) Used Size (KB)%\u0027\u0027 \r\n", "\tAND ls.counter_name LIKE N\u0027\u0027Log File(s) Size (KB)%\u0027\u0027\r\n", "\tAND ls.cntr_value > 0 AND ls.cntr_value > 0\u0027 + CASE WHEN @dbScope IS NOT NULL THEN CHAR(10) + \u0027 AND db.[database_id] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY [Database_Name]\t\r\n", "OPTION (RECOMPILE)\u0027\r\n", "\tEND\r\n", "\tEXECUTE sp_executesql @sqlcmd;\r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Database_Files\u0027 AS [Information], DB_NAME(database_id) AS [Database_Name], [file_id], type_desc, data_space_id AS [Filegroup], name, physical_name,\r\n", "\t\tstate_desc, (size * 8) / 1024 AS size_MB, CASE max_size WHEN -1 THEN \u0027Unlimited\u0027 ELSE CONVERT(VARCHAR(10), max_size) END AS max_size,\r\n", "\t\tCASE WHEN is_percent_growth = 0 THEN CONVERT(VARCHAR(10),((growth * 8) / 1024)) ELSE growth END AS [growth], CASE WHEN is_percent_growth = 1 THEN \u0027Pct\u0027 ELSE \u0027MB\u0027 END AS growth_type,\r\n", "\t\tis_media_read_only, is_read_only, is_sparse, is_name_reserved\r\n", "\tFROM #tmpdbfiledetail\r\n", "\tORDER BY database_id, [file_id];\r\n", "\tIF @sqlmajorver >= 12\r\n", "BEGIN\r\n", "\t\t/*DECLARE @dbid int, @dbname VARCHAR(1000), @sqlcmd NVARCHAR(4000)*/\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblInMemDBs\u0027))\r\n", "\tDROP TABLE #tblInMemDBs;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblInMemDBs\u0027))\r\n", "\tCREATE TABLE #tblInMemDBs\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[Has_MemoryOptimizedObjects] bit,\r\n", "\t\t\t[MemoryAllocated_MemoryOptimizedObjects_KB] DECIMAL(18,2),\r\n", "\t\t\t[MemoryUsed_MemoryOptimizedObjects_KB] DECIMAL(18,2)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (N\u0027 |-Starting Storage analysis for In-Memory OLTP Engine\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], ISNULL((SELECT 1 FROM sys.filegroups FG WHERE FG.[type] = \u0027\u0027FX\u0027\u0027), 0) AS [Has_MemoryOptimizedObjects],\r\n", "ISNULL((SELECT CONVERT(DECIMAL(18,2), (SUM(tms.memory_allocated_for_table_kb) + SUM(tms.memory_allocated_for_indexes_kb))) FROM sys.dm_db_xtp_table_memory_stats tms), 0.00) AS [MemoryAllocated_MemoryOptimizedObjects_KB],\r\n", "ISNULL((SELECT CONVERT(DECIMAL(18,2),(SUM(tms.memory_used_by_table_kb) + SUM(tms.memory_used_by_indexes_kb))) FROM sys.dm_db_xtp_table_memory_stats tms), 0.00) AS [MemoryUsed_MemoryOptimizedObjects_KB];\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblInMemDBs\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Storage analysis for In-Memory OLTP Engine subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT([DBName])\r\n", "\t\tFROM #tblInMemDBs\r\n", "\t\tWHERE [Has_MemoryOptimizedObjects] = 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027InMem_Database_Storage\u0027 AS [Information], DBName AS [Database_Name],\r\n", "\t\t\t\t[MemoryAllocated_MemoryOptimizedObjects_KB], [MemoryUsed_MemoryOptimizedObjects_KB]\r\n", "\t\t\tFROM #tblInMemDBs\r\n", "\t\t\tWHERE Has_MemoryOptimizedObjects = 1\r\n", "\t\t\tORDER BY DBName;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027InMem_Database_Storage\u0027 AS [Information], \u0027[NA]\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tEND;\r\n", "-- http://support.microsoft.com/kb/2857849\r\n", "\tIF @sqlmajorver > 10 AND @IsHadrEnabled = 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027AlwaysOn_AG_Databases\u0027 AS [Information], dc.database_name AS [Database_Name],\r\n", "\t\t\td.synchronization_health_desc, d.synchronization_state_desc, d.database_state_desc\r\n", "\t\tFROM sys.dm_hadr_database_replica_states d\r\n", "\t\t\tINNER JOIN sys.availability_databases_cluster dc ON d.group_database_id=dc.group_database_id\r\n", "\t\tWHERE d.is_local=1\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "a7c040ef-9366-437a-beba-3b838e7af706", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Database file autogrows last 72h subsection\r\n" ], "metadata": { "azdata_cell_guid": "699421c8-ea8d-4302-af5c-1947012d65ee" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting database file autogrows last 72h\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT TOP 1\r\n", "\t\tid\r\n", "\tFROM sys.traces\r\n", "\tWHERE is_default = 1)\r\n", "BEGIN\r\n", "\t\tDECLARE @tracefilename VARCHAR(500)\r\n", "\t\tIF @ostype = \u0027Windows\u0027\r\n", "\tSELECT @tracefilename = LEFT([path],LEN([path]) - PATINDEX(\u0027%\\%\u0027, REVERSE([path]))) + \u0027\\log.trc\u0027\r\n", "\t\tFROM sys.traces\r\n", "\t\tWHERE is_default = 1;\r\n", "\t\tIF @ostype <> \u0027Windows\u0027\r\n", "\tSELECT @tracefilename = LEFT([path],LEN([path]) - PATINDEX(\u0027%/%\u0027, REVERSE([path]))) + \u0027/log.trc\u0027\r\n", "\t\tFROM sys.traces\r\n", "\t\tWHERE is_default = 1;\r\n", "\t\tWITH\r\n", "\t\t\tAutoGrow_CTE (databaseid, [filename], Growth, Duration, StartTime, EndTime)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT databaseid, [filename], SUM(IntegerData*8) AS Growth, Duration, StartTime, EndTime--, CASE WHEN EventClass =\r\n", "\t\t\t\tFROM sys.fn_trace_gettable(@tracefilename, default)\r\n", "\t\t\t\tWHERE EventClass >= 92 AND EventClass <= 95 AND DATEDIFF(hh,StartTime,GETDATE()) < 72\r\n", "\t\t\t-- Last 24h\r\n", "\t\t\t\tGROUP BY databaseid, [filename], IntegerData, Duration, StartTime, EndTime\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Recorded_Autogrows_Lst72H\u0027 AS [Information], DB_NAME(database_id) AS Database_Name,\r\n", "\t\t\tmf.name AS logical_file_name, mf.size*8 / 1024 AS size_MB, mf.type_desc,\r\n", "\t\t\tag.Growth AS [growth_KB], CASE WHEN is_percent_growth = 1 THEN \u0027Pct\u0027 ELSE \u0027MB\u0027 END AS growth_type,\r\n", "\t\t\tDuration/1000 AS Growth_Duration_ms, ag.StartTime, ag.EndTime\r\n", "\t\tFROM sys.master_files mf\r\n", "\t\t\tLEFT OUTER JOIN AutoGrow_CTE ag ON mf.database_id=ag.databaseid AND mf.name=ag.[filename]\r\n", "\t\tWHERE ag.Growth > 0\r\n", "\t--Only where growth occurred\r\n", "\t\tGROUP BY database_id, mf.name, mf.size, ag.Growth, ag.Duration, ag.StartTime, ag.EndTime, is_percent_growth, mf.growth, mf.type_desc\r\n", "\t\tORDER BY Database_Name, logical_file_name, ag.StartTime;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Recorded_Autogrows_Lst72H\u0027 AS [Information], \u0027[WARNING: Could not gather information on autogrow times]\u0027 AS [Comment]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "92ef7e2f-3dd2-4753-90fd-770e16425d79", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--Database triggers subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "1d0dff0a-387d-4ef7-8309-f84a97264e28" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting database triggers\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t/*DECLARE @dbid int, @dbname VARCHAR(1000), @sqlcmd NVARCHAR(4000)*/\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTriggers\u0027))\r\n", "\tDROP TABLE #tblTriggers;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTriggers\u0027))\r\n", "\tCREATE TABLE #tblTriggers\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[triggerName] sysname,\r\n", "\t\t\t[schemaName] sysname,\r\n", "\t\t\t[tableName] sysname,\r\n", "\t\t\t[type_desc] NVARCHAR(60),\r\n", "\t\t\t[parent_class_desc] NVARCHAR(60),\r\n", "\t\t\t[create_date] DATETIME,\r\n", "\t\t\t[modify_date] DATETIME,\r\n", "\t\t\t[is_disabled] bit,\r\n", "\t\t\t[is_instead_of_trigger] bit,\r\n", "\t\t\t[is_not_for_replication] bit\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT N\u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], st.name, ss.name, stb.name, st.type_desc, st.parent_class_desc, st.create_date, st.modify_date, st.is_disabled, st.is_instead_of_trigger, st.is_not_for_replication\r\n", "FROM sys.triggers AS st\r\n", "INNER JOIN sys.tables stb ON st.parent_id = stb.[object_id]\r\n", "INNER JOIN sys.schemas ss ON stb.[schema_id] = ss.[schema_id]\r\n", "WHERE st.is_ms_shipped = 0\r\n", "ORDER BY stb.name, st.name;\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblTriggers\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Database triggers subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT([triggerName])\r\n", "\t\tFROM #tblTriggers) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Database_Triggers\u0027 AS [Information], DBName AS [Database_Name],\r\n", "\t\t\t\ttriggerName AS [Trigger_Name], schemaName AS [Schema_Name], tableName AS [Table_Name],\r\n", "\t\t\t\ttype_desc AS [Trigger_Type], parent_class_desc AS [Trigger_Parent],\r\n", "\t\t\t\tCASE is_instead_of_trigger WHEN 1 THEN \u0027INSTEAD_OF\u0027 ELSE \u0027AFTER\u0027 END AS [Trigger_Behavior],\r\n", "\t\t\t\tcreate_date, modify_date,\r\n", "\t\t\t\tCASE WHEN is_disabled = 1 THEN \u0027YES\u0027 ELSE \u0027NO\u0027 END AS [is_disabled],\r\n", "\t\t\t\tCASE WHEN is_not_for_replication = 1 THEN \u0027YES\u0027 ELSE \u0027NO\u0027 END AS [is_not_for_replication]\r\n", "\t\t\tFROM #tblTriggers\r\n", "\t\t\tORDER BY DBName, tableName, triggerName;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Database_Triggers\u0027 AS [Information], \u0027[NA]\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "d7609df6-4c05-429a-bc75-49d7420d0981", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Feature usage subsection\r\n" ], "metadata": { "azdata_cell_guid": "8d15db32-00dd-4c34-8fca-c649e3510149" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 9\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027|-Starting Feature usage\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t/*DECLARE @dbid int, @dbname VARCHAR(1000), @sqlcmd NVARCHAR(4000)*/\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerSku\u0027))\r\n", "\tDROP TABLE #tblPerSku;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerSku\u0027))\r\n", "\tCREATE TABLE #tblPerSku\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname NULL,\r\n", "\t\t\t[Feature_Name] VARCHAR(100)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], feature_name FROM sys.dm_db_persisted_sku_features (NOLOCK)\r\n", "UNION ALL\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Change_Tracking\u0027\u0027 AS feature_name FROM sys.change_tracking_databases (NOLOCK) WHERE database_id = DB_ID()\r\n", "UNION ALL\r\n", "SELECT TOP 1 \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Fine_grained_auditing\u0027\u0027 AS feature_name FROM sys.database_audit_specifications (NOLOCK)\u0027\r\n", "\t\t\t\tIF @sqlmajorver >= 13\r\n", "\t\t\tSET @sqlcmd = @sqlcmd + CHAR(10) + \u0027UNION ALL\r\n", "SELECT TOP 1 \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Polybase\u0027\u0027 AS feature_name FROM sys.external_data_sources (NOLOCK)\r\n", "UNION ALL\r\n", "SELECT TOP 1 \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Row_Level_Security\u0027\u0027 AS feature_name FROM sys.security_policies (NOLOCK)\r\n", "UNION ALL\r\n", "SELECT TOP 1 \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Always_Encrypted\u0027\u0027 AS feature_name FROM sys.column_master_keys (NOLOCK)\r\n", "UNION ALL\r\n", "SELECT TOP 1 \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbname], \u0027\u0027Dynamic_Data_Masking\u0027\u0027 AS feature_name FROM sys.masked_columns (NOLOCK) WHERE is_masked = 1\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblPerSku\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Feature usage subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF @sqlmajorver > 10 AND ((@sqlmajorver = 13 AND @sqlbuild < 4000) OR @sqlmajorver < 13) AND @IsHadrEnabled = 1\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblPerSku\r\n", "\t\t\tSELECT [dbname], \u0027Always_On\u0027 AS feature_name\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE is_database_joined = 1;\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(DISTINCT [name])\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE database_id NOT IN (2,3) AND source_database_id IS NOT NULL) > 0 -- Snapshot\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblPerSku\r\n", "\t\t\tSELECT DISTINCT [name], \u0027DB_Snapshot\u0027 AS feature_name\r\n", "\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\tWHERE database_id NOT IN (2,3) AND source_database_id IS NOT NULL;\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(DISTINCT [name])\r\n", "\t\tFROM master.sys.master_files (NOLOCK)\r\n", "\t\tWHERE database_id NOT IN (2,3) AND [type] = 2 and file_guid IS NOT NULL) > 0 -- Filestream\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblPerSku\r\n", "\t\t\tSELECT DISTINCT DB_NAME(database_id), \u0027Filestream\u0027 AS feature_name\r\n", "\t\t\tFROM sys.master_files (NOLOCK)\r\n", "\t\t\tWHERE database_id NOT IN (2,3) AND [type] = 2 and file_guid IS NOT NULL;\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT([Feature_Name])\r\n", "\t\tFROM #tblPerSku) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Feature_usage\u0027 AS [Check], \u0027[INFORMATION: Some databases are using features that are not common to all editions]\u0027 AS [Comment]\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Feature_usage\u0027 AS [Information], DBName AS [Database_Name], [Feature_Name]\r\n", "\t\t\tFROM #tblPerSku\r\n", "\t\t\tORDER BY 2, 3\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Feature_usage\u0027 AS [Check], \u0027[NA]\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "a40d8532-8ae7-4a5e-9129-f643ef4555d5", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Backups since last Full Information subsection\r\n" ], "metadata": { "azdata_cell_guid": "b51506ee-c4e8-49ba-9a12-5ce6cd6cd61d" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Backups\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @sqlmajorver > 10\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Backups_since_last_Full\u0027\u0027 AS [Information], \r\n", "[database_name] AS [Database_Name], CASE WHEN type = \u0027\u0027D\u0027\u0027 THEN \u0027\u0027Database\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027I\u0027\u0027 THEN \u0027\u0027Diff_Database\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027L\u0027\u0027 THEN \u0027\u0027Log\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027F\u0027\u0027 THEN \u0027\u0027File\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027G\u0027\u0027 THEN \u0027\u0027Diff_file\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027P\u0027\u0027 THEN \u0027\u0027Partial\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027Q\u0027\u0027 THEN \u0027\u0027Diff_partial\u0027\u0027\r\n", "\tELSE NULL END AS [bck_type],\r\n", "[backup_start_date], [backup_finish_date],\r\n", "CONVERT(decimal(20,2),backup_size/1024.00/1024.00) AS [backup_size_MB],\r\n", "CONVERT(decimal(20,2),compressed_backup_size/1024.00/1024.00) AS [compressed_backup_size_MB],\r\n", "[recovery_model], [user_name],\r\n", "database_backup_lsn AS [full_base_lsn], [differential_base_lsn], [expiration_date], \r\n", "[is_password_protected], [has_backup_checksums], [is_readonly], is_copy_only, [has_incomplete_metadata] AS [Tail_log]\r\n", "FROM msdb.dbo.backupset bck1 (NOLOCK)\r\n", "WHERE is_copy_only = 0 -- No COPY_ONLY backups\r\n", "AND backup_start_date >= (SELECT MAX(backup_start_date) FROM msdb.dbo.backupset bck2 (NOLOCK) WHERE bck2.type IN (\u0027\u0027D\u0027\u0027,\u0027\u0027F\u0027\u0027,\u0027\u0027P\u0027\u0027) AND is_copy_only = 0 AND bck1.database_name = bck2.database_name)\r\n", "ORDER BY database_name, backup_start_date DESC\u0027\r\n", "\tEND\r\n", "ELSE \r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Information\u0027\u0027 AS [Category], \u0027\u0027Backups_since_last_Full\u0027\u0027 AS [Information], \r\n", "[database_name] AS [Database_Name], CASE WHEN type = \u0027\u0027D\u0027\u0027 THEN \u0027\u0027Database\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027I\u0027\u0027 THEN \u0027\u0027Diff_Database\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027L\u0027\u0027 THEN \u0027\u0027Log\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027F\u0027\u0027 THEN \u0027\u0027File\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027G\u0027\u0027 THEN \u0027\u0027Diff_file\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027P\u0027\u0027 THEN \u0027\u0027Partial\u0027\u0027\r\n", "\tWHEN type = \u0027\u0027Q\u0027\u0027 THEN \u0027\u0027Diff_partial\u0027\u0027\r\n", "\tELSE NULL END AS [bck_type],\r\n", "[backup_start_date], [backup_finish_date], \r\n", "CONVERT(decimal(20,2),backup_size/1024.00/1024.00) AS [backup_size_MB],\r\n", "\u0027\u0027[NA]\u0027\u0027 AS [compressed_backup_size_MB], \r\n", "[recovery_model], [user_name],\r\n", "database_backup_lsn AS [full_base_lsn], [differential_base_lsn], [expiration_date], \r\n", "[is_password_protected], [has_backup_checksums], [is_readonly], is_copy_only, [has_incomplete_metadata] AS [Tail_log]\r\n", "FROM msdb.dbo.backupset bck1 (NOLOCK)\r\n", "WHERE is_copy_only = 0 -- No COPY_ONLY backups\r\n", "AND backup_start_date >= (SELECT MAX(backup_start_date) FROM msdb.dbo.backupset bck2 (NOLOCK) WHERE bck2.type IN (\u0027\u0027D\u0027\u0027,\u0027\u0027F\u0027\u0027,\u0027\u0027P\u0027\u0027) AND is_copy_only = 0 AND bck1.database_name = bck2.database_name)\r\n", "ORDER BY database_name, backup_start_date DESC\u0027\r\n", "\tEND;\r\n", "\tEXECUTE sp_executesql @sqlcmd;\r\n" ], "metadata": { "azdata_cell_guid": "7875de02-c520-4070-8c83-61b8f6fc26b1", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### System Configuration subsection\r\n" ], "metadata": { "azdata_cell_guid": "b4b5f548-66cc-4f0e-b4c5-0ea33e0997c6" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting System Configuration\u0027, 10, 1) WITH NOWAIT\r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027All_System_Configurations\u0027 AS [Information],\r\n", "\t\tname AS [Name],\r\n", "\t\tconfiguration_id AS [Number],\r\n", "\t\tminimum AS [Minimum],\r\n", "\t\tmaximum AS [Maximum],\r\n", "\t\tis_dynamic AS [Dynamic],\r\n", "\t\tis_advanced AS [Advanced],\r\n", "\t\tvalue AS [ConfigValue],\r\n", "\t\tvalue_in_use AS [RunValue],\r\n", "\t\tdescription AS [Description]\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tORDER BY name\r\n", "\tOPTION\r\n", "\t(RECOMPILE);\r\n" ], "metadata": { "azdata_cell_guid": "8607d4b1-c705-4e10-b63d-e2f9ac5e3542", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--## Database Pre-checks section\r\n", "This block is required to be run before later blocks which gather information about the databases on the instance\r\n", "- You can set the @DbScope variable below to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n" ], "metadata": { "azdata_cell_guid": "111039ca-1bf9-4feb-88e1-177ec9eb1802" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027Starting Pre-Checks - Building DB list excluding MS shipped\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @MSdb int\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs1\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs1;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs1\u0027))\r\n", "CREATE TABLE tempdb.dbo.tmpdbs1\r\n", "\t(\r\n", "\t\tid int IDENTITY(1,1),\r\n", "\t\t[dbid] int,\r\n", "\t\t[dbname] NVARCHAR(1000),\r\n", "\t\t[role] tinyint,\r\n", "\t\t[secondary_role_allow_connections] tinyint,\r\n", "\t\tisdone bit\r\n", "\t)\r\n", "\tRAISERROR (N\u0027|-Excluding MS shipped by standard names and databases belonging to non-readable AG secondary replicas (if available)\u0027, 10, 1) WITH NOWAIT\r\n", "-- Ignore MS shipped databases and databases belonging to non-readable AG secondary replicas\r\n", "\tINSERT INTO tempdb.dbo.tmpdbs1\r\n", "\t\t([dbid], [dbname], [role], [secondary_role_allow_connections], [isdone])\r\n", "\tSELECT [dbid], [dbname], [role], [secondary_role_allow_connections], 0\r\n", "\tFROM tempdb.dbo.tmpdbs0 (NOLOCK)\r\n", "\tWHERE is_read_only = 0 AND [state] = 0 AND [dbid] > 4 AND is_distributor = 0\r\n", "\t\tAND [role] <> 2 AND (secondary_role_allow_connections <> 0 OR secondary_role_allow_connections IS NULL)\r\n", "\t\tAND lower([dbname]) NOT IN (\u0027virtualmanagerdb\u0027, --Virtual Machine Manager\r\n", "\t\t\u0027scspfdb\u0027, --Service Provider Foundation\r\n", "\t\t\u0027semanticsdb\u0027, --Semantic Search\r\n", "\t\t\u0027servicemanager\u0027,\u0027service manager\u0027,\u0027dwstagingandconfig\u0027,\u0027dwrepository\u0027,\u0027dwdatamart\u0027,\u0027dwasdatabase\u0027,\u0027omdwdatamart\u0027,\u0027cmdwdatamart\u0027, --SCSM\r\n", "\t\t\u0027ssodb\u0027,\u0027bamanalysis\u0027,\u0027bamarchive\u0027,\u0027bamalertsapplication\u0027,\u0027bamalertsnsmain\u0027,\u0027bamprimaryimport\u0027,\u0027bamstarschema\u0027,\u0027biztalkmgmtdb\u0027,\u0027biztalkmsgboxdb\u0027,\u0027biztalkdtadb\u0027,\u0027biztalkruleenginedb\u0027,\u0027bamprimaryimport\u0027,\u0027biztalkedidb\u0027,\u0027biztalkhwsdb\u0027,\u0027tpm\u0027,\u0027biztalkanalysisdb\u0027,\u0027bamprimaryimportsuccessfully\u0027, --BizTalk\r\n", "\t\t\u0027aspstate\u0027,\u0027aspnet\u0027, --ASP.NET\r\n", "\t\t\u0027mscrm_config\u0027, --Dynamics CRM\r\n", "\t\t\u0027cpsdyn\u0027,\u0027lcslog\u0027,\u0027lcscdr\u0027,\u0027lis\u0027,\u0027lyss\u0027,\u0027mgc\u0027,\u0027qoemetrics\u0027,\u0027rgsconfig\u0027,\u0027rgsdyn\u0027,\u0027rtc\u0027,\u0027rtcab\u0027,\u0027rtcab1\u0027,\u0027rtcdyn\u0027,\u0027rtcshared\u0027,\u0027rtcxds\u0027,\u0027xds\u0027, --Lync\r\n", "\t\t\u0027activitylog\u0027,\u0027branchdb\u0027,\u0027clienttracelog\u0027,\u0027eventlog\u0027,\u0027listingssettings\u0027,\u0027servicegroupdb\u0027,\u0027tservercontroller\u0027,\u0027vodbackend\u0027, --MediaRoom\r\n", "\t\t\u0027operationsmanager\u0027,\u0027operationsmanagerdw\u0027,\u0027operationsmanagerac\u0027, --SCOM\r\n", "\t\t\u0027orchestrator\u0027, --Orchestrator\r\n", "\t\t\u0027sso\u0027,\u0027wss_search\u0027,\u0027wss_search_config\u0027,\u0027sharedservices_db\u0027,\u0027sharedservices_search_db\u0027,\u0027wss_content\u0027,\u0027profiledb\u0027, \u0027social db\u0027,\u0027sync db\u0027,--Sharepoint\r\n", "\t\t\u0027susdb\u0027, --WSUS\r\n", "\t\t\u0027projectserver_archive\u0027,\u0027projectserver_draft\u0027,\u0027projectserver_published\u0027,\u0027projectserver_reporting\u0027, --Project Server\r\n", "\t\t\u0027reportserver\u0027,\u0027reportservertempdb\u0027,\u0027rsdb\u0027,\u0027rstempdb\u0027, --SSRS\r\n", "\t\t\u0027fastsearchadmindatabase\u0027, --Fast Search\r\n", "\t\t\u0027ppsmonitoring\u0027,\u0027ppsplanningservice\u0027,\u0027ppsplanningsystem\u0027, --PerformancePoint Services\r\n", "\t\t\u0027dynamics\u0027, --Dynamics GP\r\n", "\t\t\u0027microsoftdynamicsax\u0027,\u0027microsoftdynamicsaxbaseline\u0027, --Dynamics AX\r\n", "\t\t\u0027fimservice\u0027,\u0027fimsynchronizationservice\u0027, --Forefront Identity Manager\r\n", "\t\t\u0027sbgatewaydatabase\u0027,\u0027sbmanagementdb\u0027, --Service Bus\r\n", "\t\t\u0027wfinstancemanagementdb\u0027,\u0027wfmanagementdb\u0027,\u0027wfresourcemanagementdb\u0027 --Workflow Manager\r\n", "\t)\r\n", "\t\tAND [dbname] NOT LIKE \u0027reportingservice[_]%\u0027 --SSRS\r\n", "\t\tAND [dbname] NOT LIKE \u0027tfs[_]%\u0027 --TFS\r\n", "\t\tAND [dbname] NOT LIKE \u0027defaultpowerpivotserviceapplicationdb%\u0027 --PowerPivot\r\n", "\t\tAND [dbname] NOT LIKE \u0027performancepoint service[_]%\u0027 --PerformancePoint Services\r\n", "\t\tAND [dbname] NOT LIKE \u0027%database nav%\u0027 --Dynamics NAV\r\n", "\t\tAND [dbname] NOT LIKE \u0027%[_]mscrm\u0027 --Dynamics CRM\r\n", "\t\tAND [dbname] NOT LIKE \u0027dpmdb[_]%\u0027 --DPM\r\n", "\t\tAND [dbname] NOT LIKE \u0027sbmessagecontainer%\u0027 --Service Bus\r\n", "\t\tAND [dbname] NOT LIKE \u0027sma%\u0027 --SCSMA\r\n", "\t\tAND [dbname] NOT LIKE \u0027releasemanagement%\u0027 --TFS Release Management\r\n", "\t\tAND [dbname] NOT LIKE \u0027projectwebapp%\u0027 --Project Server\r\n", "\t\tAND [dbname] NOT LIKE \u0027sms[_]%\u0027 AND [dbname] NOT LIKE \u0027cm[_]%\u0027 --SCCM\r\n", "\t\tAND [dbname] NOT LIKE \u0027fepdw%\u0027 AND [dbname] NOT LIKE \u0027FEPDB[_]%\u0027 --Forefront Endpoint Protection\r\n", "\t--Sharepoint\r\n", "\t\tAND [dbname] NOT LIKE \u0027sharepoint[_]admincontent%\u0027 AND [dbname] NOT LIKE \u0027sharepoint[_]config%\u0027 AND [dbname] NOT LIKE \u0027wss[_]content%\u0027 AND [dbname] NOT LIKE \u0027wss[_]search%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027sharedservices[_]db%\u0027 AND [dbname] NOT LIKE \u0027sharedservices[_]search[_]db%\u0027 AND [dbname] NOT LIKE \u0027sharedservices[_][_]db%\u0027 AND [dbname] NOT LIKE \u0027sharedservices[_][_]search[_]db%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027sharedservicescontent%\u0027 AND [dbname] NOT LIKE \u0027application[_]registry[_]service[_]db%\u0027 AND [dbname] NOT LIKE \u0027search[_]service[_]application[_]propertystoredb[_]%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027subscriptionsettings[_]%\u0027 AND [dbname] NOT LIKE \u0027webanalyticsserviceapplication[_]stagingdb[_]%\u0027 AND [dbname] NOT LIKE \u0027webanalyticsserviceapplication[_]reportingdb[_]%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027bdc[_]service[_]db[_]%\u0027 AND [dbname] NOT LIKE \u0027managed metadata service[_]%\u0027 AND [dbname] NOT LIKE \u0027performancepoint service application[_]%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027search[_]service[_]application[_]crawlstoredb[_]%\u0027 AND [dbname] NOT LIKE \u0027search[_]service[_]application[_]db[_]%\u0027 AND [dbname] NOT LIKE \u0027secure[_]store[_]service[_]db[_]%\u0027 AND [dbname] NOT LIKE \u0027stateservice%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027user profile service application[_]profiledb[_]%\u0027 AND [dbname] NOT LIKE \u0027user profile service application[_]syncdb[_]%\u0027 AND [dbname] NOT LIKE \u0027user profile service application[_]socialdb[_]%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027wordautomationservices[_]%\u0027 AND [dbname] NOT LIKE \u0027wss[_]logging%\u0027 AND [dbname] NOT LIKE \u0027wss[_]usageapplication%\u0027 AND [dbname] NOT LIKE \u0027appmng[_]service[_]db%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027search[_]service[_]application[_]analyticsreportingstoredb[_]%\u0027 AND [dbname] NOT LIKE \u0027search[_]service[_]application[_]linksstoredb[_]%\u0027 AND [dbname] NOT LIKE \u0027sharepoint[_]logging[_]%\u0027\r\n", "\t\tAND [dbname] NOT LIKE \u0027settingsservicedb%\u0027 AND [dbname] NOT LIKE \u0027sharepoint[_]logging[_]%\u0027 AND [dbname] NOT LIKE \u0027translationservice[_]%\u0027 AND [dbname] NOT LIKE \u0027sharepoint translation services[_]%\u0027 AND [dbname] NOT LIKE \u0027sessionstateservice%\u0027\r\n", "\tIF EXISTS (SELECT name\r\n", "\tFROM msdb.sys.objects (NOLOCK)\r\n", "\tWHERE name=\u0027MSdistributiondbs\u0027 AND is_ms_shipped = 1) \r\n", "BEGIN\r\n", "\t\tDELETE FROM tempdb.dbo.tmpdbs1 WHERE [dbid] IN (SELECT DB_ID(name)\r\n", "\t\tFROM msdb.dbo.MSdistributiondbs)\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Excluding MS shipped by notable object names\u0027, 10, 1) WITH NOWAIT\r\n", "-- Removing other noticeable MS shipped DBs\r\n", "\tWHILE (SELECT COUNT(id)\r\n", "\tFROM tempdb.dbo.tmpdbs1\r\n", "\tWHERE isdone = 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT TOP 1\r\n", "\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0\r\n", "\t\tSET @sqlcmd = N\u0027USE \u0027 + QUOTENAME(@dbname) + N\u0027;\r\n", "IF (OBJECT_ID(\u0027\u0027dbo.AR_Class\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.AR_Entity\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.AR_System\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_ar_CreateEntity\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_ar_CreateMethod\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Versions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL \r\n", "\tAND (OBJECT_ID(\u0027\u0027dbo.ECMApplicationLog\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.ECMTerm\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_ECM_GetPackage\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_ECM_GetGroups\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.Configuration\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MonthlyPartitions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Search_GetCrawlPipeline\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.prc_EnumSandboxedRequests\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.MSSConfiguration\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MSSOrdinal\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_MSS_GetConfigurationProperty\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.Tenants\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_Admin_ListPartitionedTables\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_DefragmentIndices\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.WAScope\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.WASetting\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027Processing\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.Groups\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Items\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_GetGroups\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_GetVersion\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.Mapping\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.PropertySet\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027SubscriptionSettingsService_Application_Pool\u0027\u0027) IS NOT NULL) \r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.Sessions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_AddItem\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_GetItemWithLock\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.SiteMap\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SiteCounts\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027WSS_Content_Application_Pools\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.PPSAnnotations\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.PPSParameterValues\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_PPS_GetAnnotation\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\t \r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.AM_Licenses\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.AM_DeploymentIds\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_AM_GetApps\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_AM_SetDeploymentId\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\t\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.MSSDefinitions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MSSSecurityDescriptors\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_MSS_GetCrawls\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", ")\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.SSSApplication\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSSAudit\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSSConfig\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_sss_GetConfig\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Actions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.VersionInfo\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.mms_extensions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027persistenceUsers\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027state_persistence_users\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.AllDocs\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.AllLists\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.NameValuePair\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_GetWorkItems\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.proc_EnumLists\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\t\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.SSO_Application\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSO_Ticket\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSO_Config\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.sso_InsertAudit\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.sso_RetrieveSSOConfig\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Sharepoint\r\n", "OR ((OBJECT_ID(\u0027\u0027dbo.ASPStateTempSessions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.ASPStateTempApplications\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL) OR OBJECT_ID(\u0027\u0027dbo.CreateTempTables\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.DeleteExpiredSessions\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.aspnet_Applications\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.aspnet_Profile\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.aspnet_Users\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.aspnet_CheckSchemaVersion\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End ASP.NET\r\n", "OR (OBJECT_ID(\u0027\u0027DataRefresh.Runs\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027GeminiService.Version\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Usage.Requests\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027HealthRule\u0027\u0027) IS NOT NULL)\r\n", "-- End PowerPivot\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.LICENSES\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.VERSION\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.TASK_RUNPROGRAM\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027Microsoft.SystemCenter.Orchestrator\u0027\u0027) IS NOT NULL)\r\n", "-- End Orchestrator\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.tbl_Cloud_Cloud\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.tbl_PXE_PxeServer\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.tbl_VMM_Server\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.prc_VMM_AddVmmServer\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.prc_Cloud_Cloud_GetParent\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End VMM\r\n", "OR (OBJECT_ID(\u0027\u0027scspf.EventHandlers\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027scspf.Servers\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027scspf.Tenants\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL)\r\n", "-- End Service Provider Foundation\r\n", "OR ((OBJECT_ID(\u0027\u0027dbo.SSOX_AuditTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSOX_GlobalInfo\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SSOX_Servers\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.sp_BackupBizTalkFull\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.ssox_spGetDBVersion\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.BizTalkDBVersion\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027BTS_ADMIN_USERS\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027BTS_OPERATORS\u0027\u0027) IS NOT NULL))\r\n", "-- End BizTalk\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Layer\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.ModelGroup\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SchemaVersion\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.XI_GetUserName\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.XU_AssignAxId\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Dynamics AX\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Notification\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SystemUserRoles\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL \r\n", "\tAND (OBJECT_ID(\u0027\u0027dbo.p_GetCrmUserId\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.p_GetPrivilegesInRole\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "\tOR (OBJECT_ID(\u0027\u0027dbo.p_AccountOVRollup\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.p_GetDbSize\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL))\r\n", "-- End Dynamics CRM\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.User Personalization\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND EXISTS(SELECT 1 FROM sys.all_objects (NOLOCK) WHERE type=\u0027\u0027U\u0027\u0027 AND (name like \u0027\u0027%$G[_]L Entry\u0027\u0027 OR name LIKE \u0027\u0027%$Item Ledger Entry\u0027\u0027)))\r\n", "-- End Dynamics NAV\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.DBVERSION\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.PATH\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SY_SQL_Options\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.zDP_ActivitySD\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Dynamics GP\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Agents\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.DistributionPoints\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SysResList\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.PXE_GetPXECert\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End SCCM\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.dtFEP_Infra_InstalledJobs\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.dtFEP_Common_User\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.dtAN_Infra_JobLastRun\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.spFEP_Infra_CreateJob\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.spAN_Infra_ScheduleJob\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Forefront Endpoint Protection\r\n", "OR (OBJECT_ID(\u0027\u0027admin.categories\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027admin.keyword\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027admin.storeentry\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL)\r\n", "-- End Fast Search\r\n", "OR (OBJECT_ID(\u0027\u0027fim.Objects\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027debug\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.mms_extensions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.mms_partition\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.mms_addmvlink\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.mms_getcsguidfromanchor\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Forefront Identity Manager\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Annotations\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.BsmUsers\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.FCObjects\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.BsmUserCreate\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.BsmUserDelete\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.DBSchemaVersion\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.QueueStatus\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.ServerStates\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.bsp_UpdateQueueSizeLimit\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End PerformancePoint Services\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Versions\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MSP_DAL_GetDatabaseCacheExceptions\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND (OBJECT_ID(\u0027\u0027dbo.MSP_DAL_GetSprocInfo\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL OR OBJECT_ID(\u0027\u0027dbo.MSP_DAL_GetSprocList\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL))\r\n", "-- End Project Server\r\n", "OR (OBJECT_ID(\u0027\u0027apm.MESSAGES\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027CS\u0027\u0027) IS NOT NULL OR SCHEMA_ID(\u0027\u0027CM\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Event_00\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MT_Database\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.PerformanceData_00\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.p_MPSelectViews\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.AemApplication\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.EventLoggingComputer\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.HealthState\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.p_MOMManagementGroupInfoSelect\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.dtMachine\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.dtPartition\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027AdtServer\u0027\u0027) IS NOT NULL)\r\n", "-- End SCOM\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.version\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND EXISTS(SELECT 1 FROM sys.internal_tables (NOLOCK) WHERE name LIKE \u0027\u0027language[_]model[_]%\u0027\u0027))\r\n", "-- End Semantic Search\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.tbComputerTarget\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.tbTarget\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.tbUpdate\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.spGetUpdateByID\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.spSearchUpdates\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End WSUS\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.tbl_DPM_InstalledUpdates\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027MSDPMExecRole\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027MSDPMRecoveryRole\u0027\u0027) IS NOT NULL)\r\n", "-- End DPM\r\n", "OR ((OBJECT_ID(\u0027\u0027dbo.DomainTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027etl.Source\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Module\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MT_Computer\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027LFXSTG.vex_Collection\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027LFX\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.DomainTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.State\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027etl\u0027\u0027) IS NOT NULL))\r\n", "-- End SCSM\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.ChunkData\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SegmentedChunk\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.SnapshotData\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027RSExecRole\u0027\u0027) IS NOT NULL)\r\n", "-- End SSRS\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.prc_ChangeHostId\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.prc_EnablePrefixCompression\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL \r\n", "AND (OBJECT_ID(\u0027\u0027dbo.tbl_RegistryItems\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.tbl_OAuthToken\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND\tOBJECT_ID(\u0027\u0027dbo.tbl_Content\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.DimBuild\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.FactCurrentWorkItem\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.FactBuildProject\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL))\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.LoadTestCase\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.LoadTestReport\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.LoadTestScenario\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.prc_GetAgents\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL\tAND OBJECT_ID(\u0027\u0027dbo.prc_QueryLoadTestRuns\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End TFS\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Release\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Server\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.TeamProject\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027System.Activities.DurableInstancing\u0027\u0027) IS NOT NULL)\r\n", "-- End TFS Release Management\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.ContainersTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Quotas\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Tenants\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.GetAllEntities\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.UpdateGatewayEntity\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.LockResourcesTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Store.Nodes\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.OperationsTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.AcquireLock\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.UpdateOperation\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.CursorsTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.LogsTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.MessagesTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.GetCursorState\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.LockEntity\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Service Bus\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.DebugTraces\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Instances\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.StoreVersionTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.GetInstanceCount\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.GetStoreVersion\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.StoreVersionTable\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Store.Clusters\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Store.Services\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Store.GetNode\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Store.UpdateCluster\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "OR (OBJECT_ID(\u0027\u0027dbo.Activities\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.Scopes\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.WorkflowServices\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.GetActivities\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027dbo.TenantCheck\u0027\u0027,\u0027\u0027P\u0027\u0027) IS NOT NULL)\r\n", "-- End Workflow Manager\r\n", "OR (OBJECT_ID(\u0027\u0027Core.Runbooks\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Core.Activities\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND OBJECT_ID(\u0027\u0027Core.Connections\u0027\u0027,\u0027\u0027U\u0027\u0027) IS NOT NULL AND SCHEMA_ID(\u0027\u0027Common\u0027\u0027) IS NOT NULL)\r\n", "-- End SCSMA\r\n", "BEGIN\r\n", "\tSELECT @MSdbOUT = \u0027 + CONVERT(VARCHAR(10), @dbid) + N\u0027\r\n", "END\u0027\r\n", "\t\tSET @params = N\u0027@MSdbOUT int OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @MSdbOUT=@MSdb OUTPUT\r\n", "\t\tIF @MSdb = @dbid\r\n", "\tBEGIN\r\n", "\t\t\tDELETE FROM tempdb.dbo.tmpdbs1 \r\n", "\t\tWHERE [dbid] = @dbid;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND\r\n", "\tEND;\r\n", "\tUPDATE tempdb.dbo.tmpdbs1\r\n", "SET isdone = 0;\r\n", "\tRAISERROR (N\u0027|-Applying 2nd layer of specific database scope, if any\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs_userchoice\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs_userchoice;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs_userchoice\u0027))\r\n", "CREATE TABLE tempdb.dbo.tmpdbs_userchoice\r\n", "\t(\r\n", "\t\t[dbid] int PRIMARY KEY,\r\n", "\t\t[dbname] NVARCHAR(1000)\r\n", "\t)\r\n", "\tIF @dbScope IS NOT NULL\r\n", "BEGIN\r\n", "\t\tSELECT @sqlcmd = \u0027SELECT [dbid], [dbname] \r\n", "FROM tempdb.dbo.tmpdbs0 (NOLOCK) \r\n", "WHERE is_read_only = 0 AND [state] = 0 AND [dbid] > 4 AND is_distributor = 0\r\n", "\tAND [role] <> 2 AND (secondary_role_allow_connections <> 0 OR secondary_role_allow_connections IS NULL)\r\n", "\tAND [dbid] IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027\r\n", "\t\tINSERT INTO tempdb.dbo.tmpdbs_userchoice\r\n", "\t\t\t([dbid], [dbname])\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\t\tSELECT @sqlcmd = \u0027DELETE FROM tempdb.dbo.tmpdbs1 WHERE [dbid] NOT IN (\u0027 + REPLACE(@dbScope,\u0027 \u0027,\u0027\u0027) + \u0027)\u0027\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND \r\n", "ELSE \r\n", "BEGIN\r\n", "\t\tSELECT @sqlcmd = \u0027SELECT [dbid], [dbname] \r\n", "FROM tempdb.dbo.tmpdbs0 (NOLOCK) \r\n", "WHERE is_read_only = 0 AND [state] = 0 AND [dbid] > 4 AND is_distributor = 0 \r\n", "\tAND [role] <> 2 AND (secondary_role_allow_connections <> 0 OR secondary_role_allow_connections IS NULL)\u0027\r\n", "\t\tINSERT INTO tempdb.dbo.tmpdbs_userchoice\r\n", "\t\t\t([dbid], [dbname])\r\n", "\t\tEXEC sp_executesql @sqlcmd;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "9d8e012e-599f-497e-8632-7e6149ed8c94", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--## Checks section\r\n" ], "metadata": { "azdata_cell_guid": "44306601-5eea-4e1c-8c54-a6a18e76654f" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027Starting Checks section\u0027, 10, 1) WITH NOWAIT\r\n", "\tRAISERROR (N\u0027|-Starting Processor Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "7458c3b1-bf93-4f8f-9eaa-07105d63c107", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Number of available Processors for this instance vs. MaxDOP setting subsection\r\n" ], "metadata": { "azdata_cell_guid": "2136f23d-9595-4b87-b06f-265a820f97f3" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Number of available Processors for this instance vs. MaxDOP setting\u0027, 10, 1) WITH NOWAIT\r\n", "\t/*c\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(1024)\r\n", "SET @cpuaffin_fixed = @cpuaffin\r\n", "SET @i = @cpucount/@numa + 1\r\n", "WHILE @i < @cpucount + @numa\r\n", "BEGIN\r\n", "\tIF (@cpucount + @numa) - @i >= CEILING(@cpucount*1.00/@numa)\r\n", "\tBEGIN\r\n", "\t\tSELECT @cpuaffin_fixed = STUFF(@cpuaffin_fixed, @i, 1, \u0027_\u0027 + SUBSTRING(@cpuaffin_fixed, @i, 1))\r\n", "\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\tSELECT @cpuaffin_fixed = STUFF(@cpuaffin_fixed, @i, CEILING(@cpucount*1.00/@numa), SUBSTRING(@cpuaffin_fixed, @i, CEILING(@cpucount*1.00/@numa)))\r\n", "\tEND\r\n", "\tSET @i = @i + CEILING(@cpucount*1.00/@numa) + 1\r\n", "END;\r\n", "*/\r\n", "-- MaxDOP should be between 8 and 15. This is handled specifically on NUMA scenarios below.\r\n", "\tSELECT @affined_cpus = COUNT(cpu_id)\r\n", "\tFROM sys.dm_os_schedulers\r\n", "\tWHERE is_online = 1 AND scheduler_id < 255 AND parent_node_id < 64;\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027affined_cpus\u0027, @affined_cpus )\r\n", "--SELECT @cpucount = COUNT(cpu_id) FROM sys.dm_os_schedulers WHERE scheduler_id < 255 AND parent_node_id < 64\r\n", "\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Parallelism_MaxDOP\u0027 AS [Check],\r\n", "\t\tCASE WHEN [value] > @affined_cpus THEN \u0027[WARNING: MaxDOP setting exceeds available processor count (affinity)\u0027\r\n", "\t\tWHEN @numa = 1 AND @affined_cpus <= 8 AND [value] > 0 AND [value] <> @affined_cpus THEN \u0027[WARNING: MaxDOP setting is not recommended for current processor count (affinity)]\u0027\r\n", "\t\tWHEN @numa = 1 AND @affined_cpus > 8 AND ([value] = 0 OR [value] > 8) THEN \u0027[WARNING: MaxDOP setting is not recommended for current processor count (affinity)]\u0027\r\n", "\t\tWHEN @sqlmajorver >= 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) <= 15 AND ([value] = 0 OR [value] > CEILING(@cpucount*1.00/@numa)) THEN \u0027[WARNING: MaxDOP setting is not recommended for current NUMA node to processor count (affinity) ratio]\u0027\r\n", "\t\tWHEN @sqlmajorver >= 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) > 15 AND ([value] = 0 OR [value] > CEILING(@cpucount*1.00/@numa/2)) THEN \u0027[WARNING: MaxDOP setting is not recommended for current NUMA node to processor count (affinity) ratio]\u0027\r\n", "\t\tWHEN @sqlmajorver < 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) < 8 AND ([value] = 0 OR [value] > CEILING(@cpucount*1.00/@numa)) THEN \u0027[WARNING: MaxDOP setting is not recommended for current NUMA node to processor count (affinity) ratio]\u0027\r\n", "\t\tWHEN @sqlmajorver < 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) >= 8 AND ([value] = 0 OR [value] > 8 OR [value] > CEILING(@cpucount*1.00/@numa)) THEN \u0027WARNING: MaxDOP setting is not recommended for current NUMA node to processor count (affinity) ratio]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation]\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027max degree of parallelism\u0027;\r\n", "\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Parallelism_MaxDOP\u0027 AS [Information],\r\n", "\t\tCASE \r\n", "\t-- If not NUMA, and up to 8 @affined_cpus then MaxDOP up to 8\r\n", "\t\tWHEN @numa = 1 AND @affined_cpus <= 8 THEN @affined_cpus\r\n", "\t-- If not NUMA, and more than 8 @affined_cpus then MaxDOP 8 \r\n", "\t\tWHEN @numa = 1 AND @affined_cpus > 8 THEN 8\r\n", "\t-- If SQL 2016 or higher and has NUMA and # logical CPUs per NUMA up to 15, then MaxDOP is set as # logical CPUs per NUMA, up to 15 \r\n", "\t\tWHEN @sqlmajorver >= 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) <= 15 THEN CEILING((@cpucount*1.00)/@numa)\r\n", "\t-- If SQL 2016 or higher and has NUMA and # logical CPUs per NUMA > 15, then MaxDOP is set as 1/2 of # logical CPUs per NUMA\r\n", "\t\tWHEN @sqlmajorver >= 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) > 15 THEN \r\n", "\t\t\tCASE WHEN CEILING(@cpucount*1.00/@numa/2) > 16 THEN 16 ELSE CEILING(@cpucount*1.00/@numa/2) END\r\n", "\t-- If up to SQL 2016 and has NUMA and # logical CPUs per NUMA up to 8, then MaxDOP is set as # logical CPUs per NUMA \r\n", "\t\tWHEN @sqlmajorver < 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) < 8 THEN CEILING(@cpucount*1.00/@numa)\r\n", "\t-- If up to SQL 2016 and has NUMA and # logical CPUs per NUMA > 8, then MaxDOP 8\r\n", "\t\tWHEN @sqlmajorver < 13 AND @numa > 1 AND CEILING(@cpucount*1.00/@numa) >= 8 THEN 8\r\n", "\t\tELSE 0\r\n", "\tEND AS [Recommended_MaxDOP],\r\n", "\t\t[value] AS [Current_MaxDOP], @cpucount AS [Available_Processors], @affined_cpus AS [Affined_Processors],\r\n", "\t-- Processor Affinity is shown highest to lowest CPU ID\r\n", "\t\t@cpuaffin_fixed AS Affinity_Mask_Bitmask\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027max degree of parallelism\u0027;\r\n" ], "metadata": { "azdata_cell_guid": "1a133df4-9e47-4209-9ff1-d5248214fd6b", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Processor Affinity in NUMA architecture subsection\r\n" ], "metadata": { "azdata_cell_guid": "07475d89-a4a1-4ea5-8552-b1d82cacf0db" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Processor Affinity in NUMA architecture\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @numa > 1\r\n", "BEGIN\r\n", "\t\tWITH\r\n", "\t\t\tncpuCTE (ncpus)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT COUNT(cpu_id) AS ncpus\r\n", "\t\t\t\tfrom sys.dm_os_schedulers\r\n", "\t\t\t\tWHERE is_online = 1 AND scheduler_id < 255 AND parent_node_id < 64\r\n", "\t\t\t\tGROUP BY parent_node_id, is_online\r\n", "\t\t\t\tHAVING COUNT(cpu_id) = 1\r\n", "\t\t\t),\r\n", "\t\t\tcpuCTE (node, afin)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT DISTINCT(parent_node_id), is_online\r\n", "\t\t\t\tFROM sys.dm_os_schedulers\r\n", "\t\t\t\tWHERE scheduler_id < 255 AND parent_node_id < 64\r\n", "\t\t\t\tGROUP BY parent_node_id, is_online\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Affinity_NUMA\u0027 AS [Check],\r\n", "\t\t\tCASE WHEN (SELECT COUNT(*)\r\n", "\t\t\tFROM ncpuCTE) > 0 THEN \u0027[WARNING: Current NUMA configuration is not recommended. At least one node has a single assigned CPU]\u0027 \r\n", "\t\t\tWHEN (SELECT COUNT(DISTINCT(node))\r\n", "\t\t\tFROM cpuCTE\r\n", "\t\t\tWHERE afin = 0 AND node NOT IN (SELECT DISTINCT(node)\r\n", "\t\t\t\tFROM cpuCTE\r\n", "\t\t\t\tWHERE afin = 1)) > 0 THEN \u0027[WARNING: Current NUMA configuration is not recommended. At least one node does not have assigned CPUs]\u0027 \r\n", "\t\t\tELSE \u0027[OK]\u0027 END AS [Deviation]\r\n", "\t\tFROM sys.dm_os_sys_info (NOLOCK)\r\n", "\t\tOPTION\r\n", "\t\t(RECOMPILE);\r\n", "\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Affinity_NUMA\u0027 AS [Information], cpu_count AS [Logical_CPU_Count],\r\n", "\t\t\t(SELECT COUNT(DISTINCT parent_node_id)\r\n", "\t\t\tFROM sys.dm_os_schedulers\r\n", "\t\t\tWHERE scheduler_id < 255 AND parent_node_id < 64) AS [NUMA_Nodes],\r\n", "\t\t-- Processor Affinity is shown highest to lowest CPU ID\r\n", "\t\t\t@cpuaffin_fixed AS Affinity_Mask_Bitmask\r\n", "\t\tFROM sys.dm_os_sys_info (NOLOCK)\r\n", "\t\tOPTION\r\n", "\t\t(RECOMPILE);\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Affinity_NUMA\u0027 AS [Check], \u0027[Not_NUMA]\u0027 AS [Deviation]\r\n", "\t\tFROM sys.dm_os_sys_info (NOLOCK)\r\n", "\t\tOPTION\r\n", "\t\t(RECOMPILE);\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "4314f181-c89b-4731-8053-8015696232e6", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Check for HP Logical Processor issue (https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c04650594) subsection\r\n" ], "metadata": { "azdata_cell_guid": "9d8d9a3d-177f-4dce-abf8-c8c197f572d4" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Check for HP Logical Processor issue\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF LOWER(@SystemManufacturer) <> \u0027microsoft\u0027 AND LOWER(@SystemManufacturer) <> \u0027vmware\u0027 AND LOWER(@ostype) = \u0027windows\u0027\r\n", "BEGIN\r\n", "\t\tIF LOWER(@BIOSVendor) = \u0027hp\u0027 AND LOWER(@Processor_Name) like \u0027%xeon%e5%\u0027 --and\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027HP Logical Processor Issue\u0027 AS [Information], \u0027[WARNING: You may be affected by HP Logical Processor issue outlined in https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c04650594]\u0027 AS [Deviation]\r\n", "\t\tEND \r\n", "\tELSE\r\n", " BEGIN\r\n", "\t\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027HP Logical Processor Issue\u0027 AS [Check], \u0027[INFORMATION: Not an affected HP Machine]\u0027 AS [Deviation];\r\n", "\t\tEND;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027HP_Logical_Processor_Issue\u0027 AS [Check], \u0027[Not a Physical Machine]\u0027 AS [Deviation];\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "8a61a840-7ea3-43ac-a148-efc1708264d8", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Additional Processor information subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "ae3c8f8e-2c37-4cd4-8af0-669efe8548df" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Additional Processor information\u0027, 10, 1) WITH NOWAIT\r\n", "-- Processor Info\r\n", "\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Processor_Summary\u0027 AS [Information], cpu_count AS [Logical_CPU_Count], hyperthread_ratio AS [Cores2Socket_Ratio],\r\n", "\t\tcpu_count/hyperthread_ratio AS [CPU_Sockets],\r\n", "\t\tCASE WHEN @numa > 1 THEN (SELECT COUNT(DISTINCT parent_node_id)\r\n", "\t\tFROM sys.dm_os_schedulers\r\n", "\t\tWHERE scheduler_id < 255 AND parent_node_id < 64) ELSE 0 END AS [NUMA_Nodes],\r\n", "\t\t@affined_cpus AS [Affined_Processors],\r\n", "\t-- Processor Affinity is shown highest to lowest Processor ID\r\n", "\t\t@cpuaffin_fixed AS Affinity_Mask_Bitmask\r\n", "\tFROM sys.dm_os_sys_info (NOLOCK)\r\n", "\tOPTION\r\n", "\t(RECOMPILE);\r\n", "\tIF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Processor utilization rate in the last 2 hours\u0027, 10, 1) WITH NOWAIT\r\n", "\t-- Processor utilization rate in the last 2 hours\r\n", "\t\tDECLARE @ts_now bigint\r\n", "\t\tDECLARE @tblAggCPU TABLE (SQLProc tinyint,\r\n", "\t\t\tSysIdle tinyint,\r\n", "\t\t\tOtherProc tinyint,\r\n", "\t\t\tMinutes tinyint)\r\n", "\t\tSELECT @ts_now = ms_ticks\r\n", "\t\tFROM sys.dm_os_sys_info (NOLOCK);\r\n", "\t\tWITH\r\n", "\t\t\tcteCPU (record_id, SystemIdle, SQLProcessUtilization, [timestamp])\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT\r\n", "\t\t\t\t\trecord.value(\u0027(./Record/@id)[1]\u0027, \u0027int\u0027) AS record_id,\r\n", "\t\t\t\t\trecord.value(\u0027(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]\u0027, \u0027int\u0027) AS SystemIdle,\r\n", "\t\t\t\t\trecord.value(\u0027(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]\u0027, \u0027int\u0027) AS SQLProcessUtilization,\r\n", "\t\t\t\t\t[TIMESTAMP]\r\n", "\t\t\t\tFROM (SELECT [TIMESTAMP], CONVERT(xml, record) AS record\r\n", "\t\t\t\t\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\t\t\t\t\tWHERE ring_buffer_type = N\u0027RING_BUFFER_SCHEDULER_MONITOR\u0027\r\n", "\t\t\t\t\t\tAND record LIKE \u0027%%\u0027) AS x\r\n", "\t\t\t)\r\n", "\t\tINSERT INTO @tblAggCPU\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 10\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -10, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 20\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -10, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -20, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 30\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -20, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -30, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 40\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -30, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -40, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 50\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -40, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -50, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 60\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -50, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -60, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 70\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -60, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -70, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 80\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -70, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -80, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 90\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -80, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -90, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 100\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -90, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -100, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 110\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -100, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -110, GETDATE())\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT AVG(SQLProcessUtilization), AVG(SystemIdle), CASE WHEN AVG(SystemIdle) + AVG(SQLProcessUtilization) < 100 THEN 100 - AVG(SystemIdle) - AVG(SQLProcessUtilization) ELSE 0 END, 120\r\n", "\t\t\tFROM cteCPU\r\n", "\t\t\tWHERE DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) <= DATEADD(mi, -110, GETDATE()) AND\r\n", "\t\t\t\tDATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) > DATEADD(mi, -120, GETDATE())\r\n", "\t\tIF (SELECT COUNT(SysIdle)\r\n", "\t\tFROM @tblAggCPU\r\n", "\t\tWHERE SysIdle < 30) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Processor_Usage_last_2h\u0027 AS [Check], \u0027[WARNING: Detected CPU usage over 70 pct]\u0027 AS [Deviation];\r\n", "\t\tEND\r\n", "\tELSE IF (SELECT COUNT(SysIdle)\r\n", "\t\tFROM @tblAggCPU\r\n", "\t\tWHERE SysIdle < 10) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Processor_Usage_last_2h\u0027 AS [Check], \u0027[WARNING: Detected CPU usage over 90 pct]\u0027 AS [Deviation];\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Processor_Usage_last_2h\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\tEND;\r\n", "\t\tSELECT \u0027Processor_checks\u0027 AS [Category], \u0027Agg_Processor_Usage_last_2h\u0027 AS [Information], SQLProc AS [SQL_Process_Utilization], SysIdle AS [System_Idle], OtherProc AS [Other_Process_Utilization], Minutes AS [Time_Slice_min]\r\n", "\t\tFROM @tblAggCPU;\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Memory Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "462fd788-706e-46e4-8288-0ecd2539f29e", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Server Memory subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "- Mind that it may take some time in servers with large caches.\r\n" ], "metadata": { "azdata_cell_guid": "e6ed939b-27cf-4651-8087-205b43ffcfc5" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Server Memory\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @minservermem bigint, @systemfreemem bigint, @numa_nodes_afinned tinyint, @LowMemoryThreshold int\r\n", "\tDECLARE @commit_target bigint\r\n", "-- Includes stolen and reserved memory in the memory manager\r\n", "\tDECLARE @committed bigint\r\n", "-- Does not include reserved memory in the memory manager\r\n", "\tDECLARE @xtp int\r\n", "\tIF @sqlmajorver = 9\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @systemmemOUT = t1.record.value(\u0027\u0027(./Record/MemoryRecord/TotalPhysicalMemory)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027)/1024, \r\n", "\t@systemfreememOUT = t1.record.value(\u0027\u0027(./Record/MemoryRecord/AvailablePhysicalMemory)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027)/1024\r\n", "FROM (SELECT MAX([TIMESTAMP]) AS [TIMESTAMP], CONVERT(xml, record) AS record \r\n", "\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\tWHERE ring_buffer_type = N\u0027\u0027RING_BUFFER_RESOURCE_MONITOR\u0027\u0027\r\n", "\t\tAND record LIKE \u0027\u0027%RESOURCE_MEMPHYSICAL%\u0027\u0027\r\n", "\tGROUP BY record) AS t1\u0027;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @systemmemOUT = total_physical_memory_kb/1024, @systemfreememOUT = available_physical_memory_kb/1024 FROM sys.dm_os_sys_memory\u0027;\r\n", "\tEND\r\n", "\tSET @params = N\u0027@systemmemOUT bigint OUTPUT, @systemfreememOUT bigint OUTPUT\u0027;\r\n", "\tEXECUTE sp_executesql @sqlcmd, @params, @systemmemOUT=@systemmem OUTPUT, @systemfreememOUT=@systemfreemem OUTPUT;\r\n", "\tIF @sqlmajorver >= 9 AND @sqlmajorver < 11\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @commit_targetOUT=bpool_commit_target*8, @committedOUT=bpool_committed*8 FROM sys.dm_os_sys_info (NOLOCK)\u0027\r\n", "\tEND\r\n", "ELSE IF @sqlmajorver >= 11\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @commit_targetOUT=committed_target_kb, @committedOUT=committed_kb FROM sys.dm_os_sys_info (NOLOCK)\u0027\r\n", "\tEND\r\n", "\tSET @params = N\u0027@commit_targetOUT bigint OUTPUT, @committedOUT bigint OUTPUT\u0027;\r\n", "\tEXECUTE sp_executesql @sqlcmd, @params, @commit_targetOUT=@commit_target OUTPUT, @committedOUT=@committed OUTPUT;\r\n", "\tSELECT @minservermem = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE [Name] = \u0027min server memory (MB)\u0027;\r\n", "\tSELECT @maxservermem = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE [Name] = \u0027max server memory (MB)\u0027;\r\n", "\tSELECT @mwthreads_count = max_workers_count\r\n", "\tFROM sys.dm_os_sys_info;\r\n", "\tSELECT @numa_nodes_afinned = COUNT (DISTINCT parent_node_id)\r\n", "\tFROM sys.dm_os_schedulers\r\n", "\tWHERE scheduler_id < 255 AND parent_node_id < 64 AND is_online = 1\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027maxservermem\u0027, @maxservermem )\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027systemmem\u0027, @systemmem )\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027mwthreads_count\u0027, @mwthreads_count )\r\n", "\t/* \r\n", "From Windows Internals book by David Solomon and Mark Russinovich:\r\n", "\"The default level of available memory that signals a low-memory-resource notification event is approximately 32 MB per 4 GB, \r\n", "to a maximum of 64 MB. The default level that signals a high-memory-resource notification event is three times the default low-memory value.\"\r\n", "*/\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1) OR ((SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_regread\u0027) = 1)\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t\tSELECT @RegKey = N\u0027System\\CurrentControlSet\\Control\\SessionManager\\MemoryManagement\u0027\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @RegKey, N\u0027LowMemoryThreshold\u0027, @LowMemoryThreshold OUTPUT, NO_OUTPUT\r\n", "\t\t\r\n", "\t\tIF @LowMemoryThreshold IS NULL\r\n", "\t\tSELECT @LowMemoryThreshold = CASE WHEN @systemmem <= 4096 THEN 32 ELSE 64 END\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Server Memory subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Missing permissions for full \"Instance info\" checks. Bypassing LowMemoryThreshold check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_issues_MaxServerMem\u0027 AS [Check],\r\n", "\t\tCASE WHEN @maxservermem = 2147483647 THEN \u0027[WARNING: MaxMem setting is default. Please revise memory settings]\u0027\r\n", "\t\tWHEN @maxservermem > @systemmem THEN \u0027[WARNING: MaxMem setting exceeds available system memory]\u0027\r\n", "\t\tWHEN SERVERPROPERTY(\u0027EditionID\u0027) IN (284895786, 1293598313) AND @maxservermem > 67108864 THEN \u0027[WARNING: MaxMem setting exceeds Web and Business Intelligence Edition limits]\u0027\r\n", "\t\tWHEN SERVERPROPERTY(\u0027EditionID\u0027) = -1534726760 AND @maxservermem > 134217728 THEN \u0027[WARNING: MaxMem setting exceeds Standard Edition limits]\u0027\r\n", "\t\tWHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 4 AND @maxservermem > 1443840 THEN \u0027[WARNING: MaxMem setting exceeds Express Edition limits]\u0027\r\n", "\t\tWHEN @numa > 1 AND (@maxservermem/@numa) * @numa_nodes_afinned > (@systemmem/@numa) * @numa_nodes_afinned THEN \u0027[WARNING: Current MaxMem setting will leverage node foreign memory. \r\n", "Maximum value for MaxMem setting on this configuration is \u0027 + CONVERT(NVARCHAR,(@systemmem/@numa) * @numa_nodes_afinned) + \u0027 for a single instance]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation], @maxservermem AS [sql_max_mem_MB];\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_issues_MinServerMem\u0027 AS [Check],\r\n", "\t\tCASE WHEN @minservermem = 0 AND (LOWER(@SystemManufacturer) = \u0027microsoft\u0027 OR LOWER(@SystemManufacturer) = \u0027vmware\u0027) THEN \u0027[WARNING: Min Server Mem setting is not set in a VM, allowing memory pressure on the Host to attempt to deallocate memory on a guest SQL Server]\u0027\r\n", "\t\tWHEN @minservermem = 0 AND @clustered = 1 THEN \u0027[INFORMATION: Min Server Mem setting is default in a clustered instance. Leverage Min Server Mem for the purpose of limiting memory concurrency between instances]\u0027\r\n", "\t\tWHEN @minservermem = @maxservermem THEN \u0027[WARNING: Min Server Mem setting is equal to Max Server Mem. This will not allow dynamic memory. Please revise memory settings]\u0027\r\n", "\t\tWHEN @numa > 1 AND (@minservermem/@numa) * @numa_nodes_afinned > (@systemmem/@numa) * @numa_nodes_afinned THEN \u0027[WARNING: Current MinMem setting will leverage node foreign memory]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation], @minservermem AS [sql_min_mem_MB];\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_issues_FreeMem\u0027 AS [Check],\r\n", "\t\tCASE WHEN (@systemfreemem*100)/@systemmem <= 5 THEN \u0027[WARNING: Less than 5 percent of Free Memory available. Please revise memory settings]\u0027\r\n", "\t\t/* 64 is the default LowMemThreshold for windows on a system with 8GB of mem or more*/\r\n", "\t\tWHEN @systemfreemem <= 64*3 THEN \u0027[WARNING: System Free Memory is dangerously low. Please revise memory settings]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation], @systemmem AS system_total_physical_memory_MB, @systemfreemem AS system_available_physical_memory_MB;\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_issues_CommitedMem\u0027 AS [Check],\r\n", "\t\tCASE WHEN @commit_target > @committed AND @sqlmajorver >= 11 THEN \u0027[INFORMATION: Memory manager will try to obtain additional memory]\u0027\r\n", "\t\tWHEN @commit_target < @committed AND @sqlmajorver >= 11 THEN \u0027[INFORMATION: Memory manager will try to shrink the amount of memory committed]\u0027\r\n", "\t\tWHEN @commit_target > @committed AND @sqlmajorver < 11 THEN \u0027[INFORMATION: Buffer Pool will try to obtain additional memory]\u0027\r\n", "\t\tWHEN @commit_target < @committed AND @sqlmajorver < 11 THEN \u0027[INFORMATION: Buffer Pool will try to shrink]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation], @commit_target/1024 AS sql_commit_target_MB, @committed/1024 AS sql_commited_MB;\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_reference\u0027 AS [Check],\r\n", "\t\tCASE WHEN @arch IS NULL THEN \u0027[WARNING: Could not determine architecture needed for check]\u0027\r\n", "\t\tWHEN (@systemmem <= 2048 AND @maxservermem > @systemmem-512-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem BETWEEN 2049 AND 4096 AND @maxservermem > @systemmem-819-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem BETWEEN 4097 AND 8192 AND @maxservermem > @systemmem-1228-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem BETWEEN 8193 AND 12288 AND @maxservermem > @systemmem-2048-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem BETWEEN 12289 AND 24576 AND @maxservermem > @systemmem-2560-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem BETWEEN 24577 AND 32768 AND @maxservermem > @systemmem-3072-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END))- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) OR\r\n", "\t\t\t(@systemmem > 32768 AND SERVERPROPERTY(\u0027EditionID\u0027) IN (284895786, 1293598313) AND @maxservermem > CAST(0.5 * (((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) + 65536) - ABS((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) - 65536)) AS int)) OR -- Find min of max mem for machine or max mem for Web and Business Intelligence SKU\r\n", "\t\t\t(@systemmem > 32768 AND SERVERPROPERTY(\u0027EditionID\u0027) = -1534726760 AND @maxservermem > CAST(0.5 * (((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) + 131072) - ABS((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) - 131072)) AS int)) OR -- Find min of max mem for machine or max mem for Standard SKU\r\n", "\t\t\t(@systemmem > 32768 AND SERVERPROPERTY(\u0027EngineEdition\u0027) IN (3,8) AND @maxservermem > @systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) THEN \u0027[WARNING: Not at the recommended MaxMem setting for this server memory configuration, with a single instance]\u0027 -- Enterprise Edition or Managed Instance\r\n", "\t\tELSE \u0027OK\u0027\r\n", "\tEND AS [Deviation],\r\n", "\t\tCASE WHEN @systemmem <= 2048 THEN @systemmem-512-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem BETWEEN 2049 AND 4096 THEN @systemmem-819-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem BETWEEN 4097 AND 8192 THEN @systemmem-1228-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem BETWEEN 8193 AND 12288 THEN @systemmem-2048-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem BETWEEN 12289 AND 24576 THEN @systemmem-2560-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem BETWEEN 24577 AND 32768 THEN @systemmem-3072-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)\r\n", "\t\tWHEN @systemmem > 32768 AND SERVERPROPERTY(\u0027EditionID\u0027) IN (284895786, 1293598313) THEN CAST(0.5 * (((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) + 65536) - ABS((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) - 65536)) AS int) -- Find min of max mem for machine or max mem for Web and Business Intelligence SKU\r\n", "\t\tWHEN @systemmem > 32768 AND SERVERPROPERTY(\u0027EditionID\u0027) = -1534726760 THEN CAST(0.5 * (((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) + 131072) - ABS((@systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END)) - 131072)) AS int) -- Find min of max mem for machine or max mem for Standard SKU\r\n", "\t\tWHEN @systemmem > 32768 AND SERVERPROPERTY(\u0027EngineEdition\u0027) IN (3,8) THEN @systemmem-4096-(@mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)- CASE WHEN @arch = 32 THEN 256 ELSE 0 END) -- Enterprise Edition or Managed Instance\r\n", "\tEND AS [Recommended_MaxMem_MB_SingleInstance],\r\n", "\t\tCASE WHEN @systemmem <= 2048 THEN 512\r\n", "\t\tWHEN @systemmem BETWEEN 2049 AND 4096 THEN 819\r\n", "\t\tWHEN @systemmem BETWEEN 4097 AND 8192 THEN 1228\r\n", "\t\tWHEN @systemmem BETWEEN 8193 AND 12288 THEN 2048\r\n", "\t\tWHEN @systemmem BETWEEN 12289 AND 24576 THEN 2560\r\n", "\t\tWHEN @systemmem BETWEEN 24577 AND 32768 THEN 3072\r\n", "\t\tWHEN @systemmem > 32768 THEN 4096\r\n", "\tEND AS [Mem_MB_for_OS],\r\n", "\t\tCASE WHEN @systemmem <= 2048 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem BETWEEN 2049 AND 4096 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem BETWEEN 4097 AND 8192 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem BETWEEN 8193 AND 12288 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem BETWEEN 12289 AND 24576 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem BETWEEN 24577 AND 32768 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\t\tWHEN @systemmem > 32768 THEN @mwthreads_count*(CASE WHEN @arch = 64 THEN 2 WHEN @arch = 128 THEN 4 WHEN @arch = 32 THEN 0.5 END)\r\n", "\tEND AS [Potential_threads_mem_MB],\r\n", "\t\t@mwthreads_count AS [Configured_workers];\r\n", "\tIF @sqlmajorver = 9\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_Summary\u0027 AS [Information],\r\n", "\t\t\t@maxservermem AS sql_max_mem_MB, @minservermem AS sql_min_mem_MB,\r\n", "\t\t\t@commit_target/1024 AS sql_commit_target_MB, --BPool in SQL 2005 to 2008R2\r\n", "\t\t\t@committed/1024 AS sql_commited_MB, --BPool in SQL 2005 to 2008R2\r\n", "\t\t\t@systemmem AS system_total_physical_memory_MB,\r\n", "\t\t\t@systemfreemem AS system_available_physical_memory_MB\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027Memory_Summary\u0027\u0027 AS [Information], \r\n", "\t@maxservermemIN AS sql_max_mem_MB, @minservermemIN AS sql_min_mem_MB, \r\n", "\t@commit_targetIN/1024 AS sql_commit_target_MB, --BPool in SQL 2005 to 2008R2\r\n", "\t@committedIN/1024 AS sql_commited_MB, --BPool in SQL 2005 to 2008R2\r\n", "\tphysical_memory_in_use_kb/1024 AS sql_physical_memory_in_use_MB, \r\n", "\tlarge_page_allocations_kb/1024 AS sql_large_page_allocations_MB, \r\n", "\tlocked_page_allocations_kb/1024 AS sql_locked_page_allocations_MB,\t\r\n", "\t@systemmemIN AS system_total_physical_memory_MB, \r\n", "\t@systemfreememIN AS system_available_physical_memory_MB, \r\n", "\ttotal_virtual_address_space_kb/1024 AS sql_total_VAS_MB, \r\n", "\tvirtual_address_space_reserved_kb/1024 AS sql_VAS_reserved_MB, \r\n", "\tvirtual_address_space_committed_kb/1024 AS sql_VAS_committed_MB, \r\n", "\tvirtual_address_space_available_kb/1024 AS sql_VAS_available_MB,\r\n", "\tpage_fault_count AS sql_page_fault_count,\r\n", "\tmemory_utilization_percentage AS sql_memory_utilization_percentage, \r\n", "\tprocess_physical_memory_low AS sql_process_physical_memory_low, \r\n", "\tprocess_virtual_memory_low AS sql_process_virtual_memory_low\t\r\n", "FROM sys.dm_os_process_memory (NOLOCK)\u0027\r\n", "\t\tSET @params = N\u0027@maxservermemIN bigint, @minservermemIN bigint, @systemmemIN bigint, @systemfreememIN bigint, @commit_targetIN bigint, @committedIN bigint\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @maxservermemIN=@maxservermem, @minservermemIN=@minservermem,@systemmemIN=@systemmem, @systemfreememIN=@systemfreemem, @commit_targetIN=@commit_target, @committedIN=@committed\r\n", "\tEND;\r\n", "\tIF @numa > 1 AND @sqlmajorver > 10\r\n", "BEGIN\r\n", "\t\tEXEC (\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027NUMA_Memory_Distribution\u0027\u0027 AS [Information], memory_node_id, virtual_address_space_reserved_kb, virtual_address_space_committed_kb, locked_page_allocations_kb, pages_kb, foreign_committed_kb, shared_memory_reserved_kb, shared_memory_committed_kb, processor_group FROM sys.dm_os_memory_nodes;\u0027)\r\n", "\tEND\r\n", "ELSE IF @numa > 1 AND @sqlmajorver = 10\r\n", "BEGIN\r\n", "\t\tEXEC (\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027NUMA_Memory_Distribution\u0027\u0027 AS [Information], memory_node_id, virtual_address_space_reserved_kb, virtual_address_space_committed_kb, locked_page_allocations_kb, single_pages_kb, multi_pages_kb, shared_memory_reserved_kb, shared_memory_committed_kb, processor_group FROM sys.dm_os_memory_nodes;\u0027)\r\n", "\tEND;\r\n", "\tIF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting RM Task\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @LowMemoryThreshold IS NOT NULL\r\n", "\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_RM_Tresholds\u0027 AS [Information], @LowMemoryThreshold AS [MEMPHYSICAL_LOW_Threshold], @LowMemoryThreshold * 3 AS [MEMPHYSICAL_HIGH_Threshold]\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Memory_RM_Notifications\u0027 AS [Information],\r\n", "\t\t\tCASE WHEN x.[TIMESTAMP] BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks BETWEEN -2147483648 AND 2147483647 THEN DATEADD(ms, x.[TIMESTAMP] - si.ms_ticks, GETDATE()) \r\n", "\t\tELSE DATEADD(s, ([TIMESTAMP]/1000) - (si.ms_ticks/1000), GETDATE()) END AS Event_Time,\r\n", "\t\t\trecord.value(\u0027(./Record/ResourceMonitor/Notification)[1]\u0027, \u0027VARCHAR(max)\u0027) AS [Notification],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/TotalPhysicalMemory)[1]\u0027, \u0027bigint\u0027)/1024 AS [Total_Physical_Mem_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailablePhysicalMemory)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_Physical_Mem_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailableVirtualAddressSpace)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_VAS_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/TotalPageFile)[1]\u0027, \u0027bigint\u0027)/1024 AS [Total_Pagefile_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailablePageFile)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_Pagefile_MB]\r\n", "\t\tFROM (SELECT [TIMESTAMP], CONVERT(xml, record) AS record\r\n", "\t\t\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\t\t\tWHERE ring_buffer_type = N\u0027RING_BUFFER_RESOURCE_MONITOR\u0027) AS x\r\n", "\tCROSS JOIN sys.dm_os_sys_info si (NOLOCK)\r\n", "\t--WHERE CASE WHEN x.[timestamp] BETWEEN -2147483648 AND 2147483648 THEN DATEADD(ms, x.[timestamp] - si.ms_ticks, GETDATE()) \r\n", "\t--\tELSE DATEADD(s, (x.[timestamp]/1000) - (si.ms_ticks/1000), GETDATE()) END >= DATEADD(hh, -12, GETDATE())\r\n", "\t\tORDER BY 2 DESC;\r\n", "\t\tRAISERROR (N\u0027 |-Starting Hand Movements from Cache Clock Hands\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(rounds_count)\r\n", "\t\tFROM sys.dm_os_memory_cache_clock_hands (NOLOCK)\r\n", "\t\tWHERE rounds_count > 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tIF @sqlmajorver >= 11\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027Clock_Hand_Notifications\u0027\u0027 AS [Information], mcch.name, mcch.[type], \r\n", "\tmcch.clock_hand, mcch.clock_status, SUM(mcch.rounds_count) AS rounds_count,\r\n", "\tSUM(mcch.removed_all_rounds_count) AS cache_entries_removed_all_rounds, \r\n", "\tSUM(mcch.removed_last_round_count) AS cache_entries_removed_last_round,\r\n", "\tSUM(mcch.updated_last_round_count) AS cache_entries_updated_last_round,\r\n", "\tSUM(mcc.pages_kb) AS cache_pages_kb,\r\n", "\tSUM(mcc.pages_in_use_kb) AS cache_pages_in_use_kb,\r\n", "\tSUM(mcc.entries_count) AS cache_entries_count, \r\n", "\tSUM(mcc.entries_in_use_count) AS cache_entries_in_use_count, \r\n", "\tCASE WHEN mcch.last_tick_time BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks BETWEEN -2147483648 AND 2147483647 THEN DATEADD(ms, mcch.last_tick_time - si.ms_ticks, GETDATE()) \r\n", "\t\tWHEN mcch.last_tick_time/1000 BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks/1000 BETWEEN -2147483648 AND 2147483647 THEN DATEADD(s, (mcch.last_tick_time/1000) - (si.ms_ticks/1000), GETDATE()) \r\n", "\t\tELSE NULL END AS last_clock_hand_move\r\n", "FROM sys.dm_os_memory_cache_counters mcc (NOLOCK)\r\n", "INNER JOIN sys.dm_os_memory_cache_clock_hands mcch (NOLOCK) ON mcc.cache_address = mcch.cache_address\r\n", "CROSS JOIN sys.dm_os_sys_info si (NOLOCK)\r\n", "WHERE mcch.rounds_count > 0\r\n", "GROUP BY mcch.name, mcch.[type], mcch.clock_hand, mcch.clock_status, mcc.pages_kb, mcc.pages_in_use_kb, mcch.last_tick_time, si.ms_ticks, mcc.entries_count, mcc.entries_in_use_count\r\n", "ORDER BY SUM(mcch.removed_all_rounds_count) DESC, mcch.[type];\u0027\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027Clock_Hand_Notifications\u0027\u0027 AS [Information], mcch.name, mcch.[type], \r\n", "\tmcch.clock_hand, mcch.clock_status, SUM(mcch.rounds_count) AS rounds_count,\r\n", "\tSUM(mcch.removed_all_rounds_count) AS cache_entries_removed_all_rounds, \r\n", "\tSUM(mcch.removed_last_round_count) AS cache_entries_removed_last_round,\r\n", "\tSUM(mcch.updated_last_round_count) AS cache_entries_updated_last_round,\r\n", "\tSUM(mcc.single_pages_kb) AS cache_single_pages_kb,\r\n", "\tSUM(mcc.multi_pages_kb) AS cache_multi_pages_kb,\r\n", "\tSUM(mcc.single_pages_in_use_kb) AS cache_single_pages_in_use_kb,\r\n", "\tSUM(mcc.multi_pages_in_use_kb) AS cache_multi_pages_in_use_kb,\r\n", "\tSUM(mcc.entries_count) AS cache_entries_count, \r\n", "\tSUM(mcc.entries_in_use_count) AS cache_entries_in_use_count, \r\n", "\tCASE WHEN mcch.last_tick_time BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks BETWEEN -2147483648 AND 2147483647 THEN DATEADD(ms, mcch.last_tick_time - si.ms_ticks, GETDATE()) \r\n", "\t\tWHEN mcch.last_tick_time/1000 BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks/1000 BETWEEN -2147483648 AND 2147483647 THEN DATEADD(s, (mcch.last_tick_time/1000) - (si.ms_ticks/1000), GETDATE()) \r\n", "\t\tELSE NULL END AS last_clock_hand_move\r\n", "FROM sys.dm_os_memory_cache_counters mcc (NOLOCK)\r\n", "INNER JOIN sys.dm_os_memory_cache_clock_hands mcch (NOLOCK) ON mcc.cache_address = mcch.cache_address\r\n", "CROSS JOIN sys.dm_os_sys_info si (NOLOCK)\r\n", "WHERE mcch.rounds_count > 0\r\n", "GROUP BY mcch.name, mcch.[type], mcch.clock_hand, mcch.clock_status, mcc.single_pages_kb, mcc.multi_pages_kb, mcc.single_pages_in_use_kb, mcc.multi_pages_in_use_kb, mcch.last_tick_time, si.ms_ticks, mcc.entries_count, mcc.entries_in_use_count\r\n", "ORDER BY SUM(mcch.removed_all_rounds_count) DESC, mcch.[type];\u0027\r\n", "\t\t\tEND\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Clock_Hand_Notifications\u0027 AS [Information], \u0027[OK]\u0027 AS Comment\r\n", "\t\tEND;\r\n", "\t\tIF @bpool_consumer = 1\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (N\u0027 |-Starting Buffer Pool Consumers from Buffer Descriptors\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t-- Note: in case of NUMA architecture, more than one entry per database is expected\r\n", "\t\t\tSET @sqlcmd = \u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027Buffer_Pool_Consumers\u0027\u0027 AS [Information], \r\n", "\tnuma_node, COUNT_BIG(DISTINCT page_id)*8/1024 AS total_pages_MB, \r\n", "\tCASE database_id WHEN 32767 THEN \u0027\u0027ResourceDB\u0027\u0027 ELSE DB_NAME(database_id) END AS database_name,\r\n", "\tSUM(CONVERT(BIGINT,row_count))/COUNT_BIG(DISTINCT page_id) AS avg_row_count_per_page, \r\n", "\tSUM(CONVERT(BIGINT, free_space_in_bytes))/COUNT_BIG(DISTINCT page_id) AS avg_free_space_bytes_per_page\r\n", "\t\u0027 + CASE WHEN @sqlmajorver >= 12 THEN \u0027,is_in_bpool_extension\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "\t\u0027 + CASE WHEN @sqlmajorver = 10 THEN \u0027,numa_node\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "\t\u0027 + CASE WHEN @sqlmajorver >= 11 THEN \u0027,AVG(read_microsec) AS avg_read_microsec\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "FROM sys.dm_os_buffer_descriptors\r\n", "--WHERE bd.page_type IN (\u0027\u0027DATA_PAGE\u0027\u0027, \u0027\u0027INDEX_PAGE\u0027\u0027)\r\n", "GROUP BY database_id\u0027 + CASE WHEN @sqlmajorver >= 10 THEN \u0027, numa_node\u0027 ELSE \u0027\u0027 END + CASE WHEN @sqlmajorver >= 12 THEN \u0027, is_in_bpool_extension\u0027 ELSE \u0027\u0027 END + \u0027\r\n", "ORDER BY total_pages_MB DESC;\u0027\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd;\r\n", "\t\tEND\r\n", "\t\tRAISERROR (N\u0027 |-Starting Memory Allocations from Memory Clerks\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], [type] AS Alloc_Type, \r\n", "\t\u0027 + CASE WHEN @sqlmajorver < 11 THEN \u0027SUM(single_pages_kb + multi_pages_kb + virtual_memory_committed_kb + shared_memory_committed_kb + awe_allocated_kb) AS Alloc_Mem_KB\u0027\r\n", "\t\tELSE \u0027SUM(pages_kb + virtual_memory_committed_kb + shared_memory_committed_kb + awe_allocated_kb) AS Alloc_Mem_KB\u0027 END + \u0027\r\n", "FROM sys.dm_os_memory_clerks \r\n", "WHERE type IN (\u0027\u0027CACHESTORE_COLUMNSTOREOBJECTPOOL\u0027\u0027,\u0027\u0027CACHESTORE_CLRPROC\u0027\u0027,\u0027\u0027CACHESTORE_OBJCP\u0027\u0027,\u0027\u0027CACHESTORE_PHDR\u0027\u0027,\u0027\u0027CACHESTORE_SQLCP\u0027\u0027,\u0027\u0027CACHESTORE_TEMPTABLES\u0027\u0027,\r\n", "\t\u0027\u0027MEMORYCLERK_SQLBUFFERPOOL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLCLR\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLGENERAL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLLOGPOOL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLOPTIMIZER\u0027\u0027,\r\n", "\t\u0027\u0027MEMORYCLERK_SQLQUERYCOMPILE\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLQUERYEXEC\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLQUERYPLAN\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLSTORENG\u0027\u0027,\u0027\u0027MEMORYCLERK_XTP\u0027\u0027,\r\n", "\t\u0027\u0027OBJECTSTORE_LOCK_MANAGER\u0027\u0027,\u0027\u0027OBJECTSTORE_SNI_PACKET\u0027\u0027,\u0027\u0027USERSTORE_DBMETADATA\u0027\u0027,\u0027\u0027USERSTORE_OBJPERM\u0027\u0027)\r\n", "GROUP BY [type]\r\n", "UNION ALL\r\n", "SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027Others\u0027\u0027 AS Alloc_Type, \r\n", "\t\u0027 + CASE WHEN @sqlmajorver < 11 THEN \u0027SUM(single_pages_kb + multi_pages_kb + virtual_memory_committed_kb + shared_memory_committed_kb) AS Alloc_Mem_KB\u0027\r\n", "\t\tELSE \u0027SUM(pages_kb + virtual_memory_committed_kb + shared_memory_committed_kb) AS Alloc_Mem_KB\u0027 END + \u0027\r\n", "FROM sys.dm_os_memory_clerks \r\n", "WHERE type NOT IN (\u0027\u0027CACHESTORE_COLUMNSTOREOBJECTPOOL\u0027\u0027,\u0027\u0027CACHESTORE_CLRPROC\u0027\u0027,\u0027\u0027CACHESTORE_OBJCP\u0027\u0027,\u0027\u0027CACHESTORE_PHDR\u0027\u0027,\u0027\u0027CACHESTORE_SQLCP\u0027\u0027,\u0027\u0027CACHESTORE_TEMPTABLES\u0027\u0027,\r\n", "\t\u0027\u0027MEMORYCLERK_SQLBUFFERPOOL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLCLR\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLGENERAL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLLOGPOOL\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLOPTIMIZER\u0027\u0027,\r\n", "\t\u0027\u0027MEMORYCLERK_SQLQUERYCOMPILE\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLQUERYEXEC\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLQUERYPLAN\u0027\u0027,\u0027\u0027MEMORYCLERK_SQLSTORENG\u0027\u0027,\u0027\u0027MEMORYCLERK_XTP\u0027\u0027,\r\n", "\t\u0027\u0027OBJECTSTORE_LOCK_MANAGER\u0027\u0027,\u0027\u0027OBJECTSTORE_SNI_PACKET\u0027\u0027,\u0027\u0027USERSTORE_DBMETADATA\u0027\u0027,\u0027\u0027USERSTORE_OBJPERM\u0027\u0027)\r\n", "ORDER BY Alloc_Mem_KB DESC\u0027\r\n", "\t\tEXECUTE sp_executesql @sqlcmd;\r\n", "\t\tIF @sqlmajorver >= 12\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @xtpOUT = COUNT(*) FROM sys.dm_db_xtp_memory_consumers\u0027;\r\n", "\t\t\tSET @params = N\u0027@xtpOUT int OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @xtpOUT = @xtp OUTPUT;\r\n", "\t\t\tIF @xtp > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR (N\u0027 |-Starting Memory Consumers from In-Memory OLTP Engine\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027InMemory_Consumers\u0027\u0027 AS Alloc_Type, \r\n", "\tOBJECT_NAME([object_id]) AS [Object_Name], memory_consumer_type_desc, [object_id], index_id, \r\n", "\tallocated_bytes/(1024*1024) AS Allocated_MB, used_bytes/(1024*1024) AS Used_MB, \r\n", "\tCASE WHEN used_bytes IS NULL THEN \u0027\u0027used_bytes_is_varheap_only\u0027\u0027 ELSE \u0027\u0027\u0027\u0027 END AS [Comment]\r\n", "FROM sys.dm_db_xtp_memory_consumers\r\n", "WHERE [object_id] > 0\r\n", "ORDER BY Allocated_MB DESC\u0027\r\n", "\t\t\t-- Only user objects; system objects are negative numbers\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd;\r\n", "\t\t\t\tRAISERROR (N\u0027 |-Starting Memory Allocations from In-Memory OLTP Engine\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Memory_checks\u0027\u0027 AS [Category], \u0027\u0027InMemory_Alloc\u0027\u0027 AS Alloc_Type, \r\n", "\tSUM(allocated_bytes)/(1024*1024) AS total_allocated_MB, SUM(used_bytes)/(1024*1024) AS total_used_MB\r\n", "FROM sys.dm_db_xtp_memory_consumers\r\n", "ORDER BY total_allocated_MB DESC\u0027\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd;\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027 |-Starting OOM\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT([TIMESTAMP])\r\n", "\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\tWHERE ring_buffer_type = N\u0027RING_BUFFER_OOM\u0027) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027OOM_Notifications\u0027 AS [Information],\r\n", "\t\t\tCASE WHEN x.[TIMESTAMP] BETWEEN -2147483648 AND 2147483647 AND si.ms_ticks BETWEEN -2147483648 AND 2147483647 THEN DATEADD(ms, x.[TIMESTAMP] - si.ms_ticks, GETDATE()) \r\n", "\t\tELSE DATEADD(s, ([TIMESTAMP]/1000) - (si.ms_ticks/1000), GETDATE()) END AS Event_Time,\r\n", "\t\t\trecord.value(\u0027(./Record/OOM/Action)[1]\u0027, \u0027varchar(50)\u0027) AS [Action],\r\n", "\t\t\trecord.value(\u0027(./Record/OOM/Resources)[1]\u0027, \u0027int\u0027) AS [Resources],\r\n", "\t\t\trecord.value(\u0027(./Record/OOM/Task)[1]\u0027, \u0027varchar(20)\u0027) AS [Task],\r\n", "\t\t\trecord.value(\u0027(./Record/OOM/Pool)[1]\u0027, \u0027int\u0027) AS [PoolID],\r\n", "\t\t\trgrp.name AS [PoolName],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/MemoryUtilization)[1]\u0027, \u0027bigint\u0027) AS [MemoryUtilPct],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/TotalPhysicalMemory)[1]\u0027, \u0027bigint\u0027)/1024 AS [Total_Physical_Mem_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailablePhysicalMemory)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_Physical_Mem_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailableVirtualAddressSpace)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_VAS_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/TotalPageFile)[1]\u0027, \u0027bigint\u0027)/1024 AS [Total_Pagefile_MB],\r\n", "\t\t\trecord.value(\u0027(./Record/MemoryRecord/AvailablePageFile)[1]\u0027, \u0027bigint\u0027)/1024 AS [Avail_Pagefile_MB]\r\n", "\t\tFROM (SELECT [TIMESTAMP], CONVERT(xml, record) AS record\r\n", "\t\t\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\t\t\tWHERE ring_buffer_type = N\u0027RING_BUFFER_OOM\u0027) AS x\r\n", "\tCROSS JOIN sys.dm_os_sys_info si (NOLOCK)\r\n", "\t\t\tLEFT JOIN sys.resource_governor_resource_pools rgrp (NOLOCK) ON rgrp.pool_id = record.value(\u0027(./Record/OOM/Pool)[1]\u0027, \u0027int\u0027)\r\n", "\t--WHERE CASE WHEN x.[timestamp] BETWEEN -2147483648 AND 2147483648 THEN DATEADD(ms, x.[timestamp] - si.ms_ticks, GETDATE()) \r\n", "\t--\tELSE DATEADD(s, (x.[timestamp]/1000) - (si.ms_ticks/1000), GETDATE()) END >= DATEADD(hh, -12, GETDATE())\r\n", "\t\tORDER BY 2 DESC;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027OOM_Notifications\u0027 AS [Information], \u0027[OK]\u0027 AS Comment\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "c9613de7-c74b-4e39-854d-ca9882b0ec97", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### LPIM subsection\r\n" ], "metadata": { "azdata_cell_guid": "b43545bf-7887-4596-9684-49a41666b141" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting LPIM\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF ((@sqlmajorver = 13 AND @sqlbuild >= 4000) OR @sqlmajorver > 13)\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @lpimOUT = CASE WHEN sql_memory_model = 2 THEN 1 ELSE 0 END FROM sys.dm_os_sys_info (NOLOCK)\u0027;\r\n", "\t\tSET @params = N\u0027@lpimOUT bit OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @lpimOUT=@lpim OUTPUT;\r\n", "\tEND\r\n", "\tIF ((@sqlmajorver = 13 AND @sqlbuild < 4000) OR (@sqlmajorver >= 10 AND @sqlmajorver < 13))\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @lpimOUT = CASE WHEN locked_page_allocations_kb > 0 THEN 1 ELSE 0 END FROM sys.dm_os_process_memory (NOLOCK)\u0027\r\n", "\t\tSET @params = N\u0027@lpimOUT bit OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @lpimOUT=@lpim OUTPUT\r\n", "\tEND\r\n", "\tIF @sqlmajorver = 9\r\n", "BEGIN\r\n", "\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\tOR ISNULL(IS_SRVROLEMEMBER(N\u0027securityadmin\u0027), 0) = 1 -- Is securityadmin\r\n", "\t\t\tOR ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_readerrorlog\u0027) > 0\r\n", "\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_readerrorlog\u0027) > 0\r\n", "\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_enumerrorlogs\u0027) > 0)\r\n", "\tBEGIN\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#lpimdbcc\u0027))\r\n", "\t\tDROP TABLE #lpimdbcc;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#lpimdbcc\u0027))\r\n", "\t\tCREATE TABLE #lpimdbcc\r\n", "\t\t\t(\r\n", "\t\t\t\tlogdate DATETIME,\r\n", "\t\t\t\tspid VARCHAR(50),\r\n", "\t\t\t\tlogmsg VARCHAR(4000)\r\n", "\t\t\t)\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#lpimavail_logs\u0027))\r\n", "\t\tDROP TABLE #lpimavail_logs;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#lpimavail_logs\u0027))\r\n", "\t\tCREATE TABLE #lpimavail_logs\r\n", "\t\t\t(\r\n", "\t\t\t\tlognum int,\r\n", "\t\t\t\tlogdate DATETIME,\r\n", "\t\t\t\tlogsize int\r\n", "\t\t\t)\r\n", "\t\t-- Get the number of available logs \r\n", "\t\t\tINSERT INTO #lpimavail_logs\r\n", "\t\t\tEXEC xp_enumerrorlogs\r\n", "\t\t\tSELECT @lognumber = MIN(lognum)\r\n", "\t\t\tFROM #lpimavail_logs\r\n", "\t\t\tWHERE DATEADD(dd, DATEDIFF(dd, 0, logdate), 0) >= DATEADD(dd, DATEDIFF(dd, 0, @StartDate), 0)\r\n", "\t\t\tSELECT @logcount = ISNULL(MAX(lognum),@lognumber)\r\n", "\t\t\tFROM #lpimavail_logs\r\n", "\t\t\tWHERE DATEADD(dd, DATEDIFF(dd, 0, logdate), 0) >= DATEADD(dd, DATEDIFF(dd, 0, @StartDate), 0)\r\n", "\t\t\tIF @lognumber IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027[WARNING: Could not retrieve information about Locked pages usage in SQL Server 2005]\u0027\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tWHILE @lognumber < @logcount \r\n", "\t\tBEGIN\r\n", "\t\t\t-- Cycle through sql error logs (Cannot use Large Page Extensions: lock memory privilege was not granted)\r\n", "\t\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027Using locked pages for buffer pool\u0027\u0027\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #lpimdbcc\r\n", "\t\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 1. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t-- Next log \r\n", "\t\t\t--SET @lognumber = @lognumber + 1 \r\n", "\t\t\t\tSELECT @lognumber = MIN(lognum)\r\n", "\t\t\t\tFROM #lpimavail_logs\r\n", "\t\t\t\tWHERE lognum > @lognumber\r\n", "\t\t\tEND\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #lpimdbcc) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @lpim = 1\r\n", "\t\t\tEND\r\n", "\t\tELSE IF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #lpimdbcc) = 0 AND @lognumber IS NOT NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @lpim = 0\r\n", "\t\t\tEND;\r\n", "\t\t\tDROP TABLE #lpimavail_logs;\r\n", "\t\t\tDROP TABLE #lpimdbcc;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin or securityadmin can run the \"Locked_pages\" check. Bypassing check]\u0027, 16, 1, N\u0027permissions\u0027)\r\n", "\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin or securityadmin, then user must be a granted EXECUTE permissions on the following sprocs to run checks: xp_enumerrorlogs and sp_readerrorlog. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND;\r\n", "\tEND\r\n", "\tIF @lpim = 0 AND CONVERT(DECIMAL(3,1), @osver) < 6.0 AND @arch = 64\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Locked_pages\u0027 AS [Check], \u0027[WARNING: Locked pages are not in use by SQL Server. In a WS2003 x64 architecture it is recommended to enable LPIM]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE IF @lpim = 1 AND CONVERT(DECIMAL(3,1), @osver) < 6.0 AND @arch = 64\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Locked_pages\u0027 AS [Check], \u0027[INFORMATION: Locked pages are being used by SQL Server. This is recommended in a WS2003 x64 architecture]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE IF @lpim = 1 AND CONVERT(DECIMAL(3,1), @osver) >= 6.0 AND @arch = 64\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Locked_pages\u0027 AS [Check], \u0027[INFORMATION: Locked pages are being used by SQL Server. This is recommended in WS2008 or above only when there are signs of paging]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE IF @lpim IS NULL\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Locked_pages\u0027 AS [Check], \u0027[Could_not_retrieve_information]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Memory_checks\u0027 AS [Category], \u0027Locked_pages\u0027 AS [Check], \u0027[Not_used]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "05819498-1b81-426c-baec-cc72174cefec", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Pagefile subsection\r\n" ], "metadata": { "azdata_cell_guid": "8bee6304-0bea-41ad-a78f-ef2ecf02862d" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Pagefile Checks\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @pf_value tinyint--, @RegKey NVARCHAR(255)\r\n", "\tDECLARE @pagefile bigint, @freepagefile bigint, @paged bigint\r\n", "\tDECLARE @tbl_pf_value TABLE (Value VARCHAR(25),\r\n", "\t\tData VARCHAR(50))\r\n", "\tIF @sqlmajorver = 9\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @pagefileOUT = (t1.record.value(\u0027\u0027(./Record/MemoryRecord/TotalPageFile)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027)-t1.record.value(\u0027\u0027(./Record/MemoryRecord/TotalPhysicalMemory)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027))/1024,\r\n", "\t@freepagefileOUT = (t1.record.value(\u0027\u0027(./Record/MemoryRecord/AvailablePageFile)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027)-t1.record.value(\u0027\u0027(./Record/MemoryRecord/AvailablePhysicalMemory)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027))/1024,\r\n", "\t@pagedOUT = ((t1.record.value(\u0027\u0027(./Record/MemoryRecord/TotalPageFile)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027)-t1.record.value(\u0027\u0027(./Record/MemoryRecord/AvailablePageFile)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027))/t1.record.value(\u0027\u0027(./Record/MemoryRecord/TotalPageFile)[1]\u0027\u0027, \u0027\u0027bigint\u0027\u0027))/1024\r\n", "FROM (SELECT MAX([TIMESTAMP]) AS [TIMESTAMP], CONVERT(xml, record) AS record \r\n", "\tFROM sys.dm_os_ring_buffers (NOLOCK)\r\n", "\tWHERE ring_buffer_type = N\u0027\u0027RING_BUFFER_RESOURCE_MONITOR\u0027\u0027\r\n", "\t\tAND record LIKE \u0027\u0027%RESOURCE_MEMPHYSICAL%\u0027\u0027\r\n", "\tGROUP BY record) AS t1\u0027;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @pagefileOUT = (total_page_file_kb-total_physical_memory_kb)/1024, \r\n", "\t@freepagefileOUT = (available_page_file_kb-available_physical_memory_kb)/1024, \r\n", "\t@pagedOUT = ((total_page_file_kb-available_page_file_kb)/total_page_file_kb) \r\n", "FROM sys.dm_os_sys_memory (NOLOCK)\u0027;\r\n", "\tEND\r\n", "\tSET @params = N\u0027@pagefileOUT bigint OUTPUT, @freepagefileOUT bigint OUTPUT, @pagedOUT bigint OUTPUT\u0027;\r\n", "\tEXECUTE sp_executesql @sqlcmd, @params, @pagefileOUT=@pagefile OUTPUT, @freepagefileOUT=@freepagefile OUTPUT, @pagedOUT=@paged OUTPUT;\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1) OR ((SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_regread\u0027) = 1)\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t\tSELECT @RegKey = N\u0027System\\CurrentControlSet\\Control\\Session Manager\\Memory Management\u0027\r\n", "\t\tINSERT INTO @tbl_pf_value\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @RegKey, N\u0027PagingFiles\u0027, NO_OUTPUT\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Pagefile subsection - Error raised in TRY block 1. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Missing permissions for full \"Pagefile\" checks. Bypassing System managed pagefile check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM @tbl_pf_value) > 0 \r\n", "BEGIN\r\n", "\t\tSELECT @pf_value = CASE WHEN (SELECT COUNT(*)\r\n", "\t\t\tFROM @tbl_pf_value\r\n", "\t\t\tWHERE Data = \u0027\u0027) > 0 THEN 1\r\n", "\t\t\tWHEN (SELECT COUNT(*)\r\n", "\t\t\tFROM @tbl_pf_value\r\n", "\t\t\tWHERE Data = \u0027?:\\pagefile.sys\u0027) > 0 THEN 2\r\n", "\t\t\tWHEN (SELECT COUNT(*)\r\n", "\t\t\tFROM @tbl_pf_value\r\n", "\t\t\tWHERE Data LIKE \u0027%:\\pagefile.sys 0 0%\u0027) > 0 THEN 3\r\n", "\t\tELSE 0 END\r\n", "\t\tFROM @tbl_pf_value\r\n", "\t\tSELECT \u0027Pagefile_checks\u0027 AS [Category], \u0027Pagefile_management\u0027 AS [Check],\r\n", "\t\t\tCASE WHEN @pf_value = 1 THEN \u0027[WARNING: No pagefile is configured]\u0027\r\n", "\t\t\tWHEN @pf_value = 2 THEN \u0027[WARNING: Pagefile is managed automatically on ALL drives]\u0027\r\n", "\t\t\tWHEN @pf_value = 3 THEN \u0027[WARNING: Pagefile is managed automatically]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027 END AS [Deviation]\r\n", "\tEND\r\n", "\tSELECT \u0027Pagefile_checks\u0027 AS [Category], \u0027Pagefile_free_space\u0027 AS [Check],\r\n", "\t\tCASE WHEN @freepagefile <= 150 THEN \u0027[WARNING: Pagefile free space is dangerously low. Please revise Pagefile settings]\u0027\r\n", "\t\tWHEN (@freepagefile*100)/@pagefile <= 10 THEN \u0027[WARNING: Less than 10 percent of Pagefile is available. Please revise Pagefile settings]\u0027\r\n", "\t\tWHEN (@freepagefile*100)/@pagefile <= 30 THEN \u0027[INFORMATION: Less than 30 percent of Pagefile is available]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027 END AS [Deviation],\r\n", "\t\t@pagefile AS total_pagefile_MB, @freepagefile AS available_pagefile_MB;\r\n", "\tSELECT \u0027Pagefile_checks\u0027 AS [Category], \u0027Pagefile_minimum_size\u0027 AS [Check],\r\n", "\t\tCASE WHEN @osver = \u00275.2\u0027 AND @arch = 64 AND @pagefile < 8192 THEN \u0027[WARNING: Pagefile is smaller than 8GB on a WS2003 x64 system. Please revise Pagefile settings]\u0027\r\n", "\t\tWHEN @osver = \u00275.2\u0027 AND @arch = 32 AND @pagefile < 2048 THEN \u0027[WARNING: Pagefile is smaller than 2GB on a WS2003 x86 system. Please revise Pagefile settings]\u0027\r\n", "\t\tWHEN @osver <> \u00275.2\u0027 THEN \u0027[NA]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027 END AS [Deviation],\r\n", "\t\t@pagefile AS total_pagefile_MB;\r\n", "\tSELECT \u0027Pagefile_checks\u0027 AS [Category], \u0027Process_paged_out\u0027 AS [Check],\r\n", "\t\tCASE WHEN @paged > 0 THEN \u0027[WARNING: Part of SQL Server process memory has been paged out. Please revise LPIM settings]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027 END AS [Deviation],\r\n", "\t\t@paged AS paged_out_MB;\r\n" ], "metadata": { "azdata_cell_guid": "9af616a0-fc29-4dd2-8cca-b79ff7e9ff6b", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--## I/O Checks section\r\n" ], "metadata": { "azdata_cell_guid": "511b40c8-33c9-444f-8269-c41a1f1192ac" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Starting I/O Stall subsection (wait for 5s) \r\n", "- I/O stall in database files over 50% of cumulative sampled time or I/O latencies over 20ms in the last 5s subsection \r\n", "- io_stall refers to user processes waited for I/O. This number can be much greater than the sample_ms. \r\n", "- Might indicate that your I/O has insufficient service capabilities (HBA queue depths, reduced throughput, etc). \r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "b237858f-88e6-4134-b3bd-97ee72ea3f9a" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "\t\tRAISERROR (N\u0027|-Starting I/O Checks\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @ptochecks = 1\r\n", "\tBEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting I/O Stall subsection (wait for 5s)\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE @mincol DATETIME, @maxcol DATETIME\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_io_virtual_file_stats\u0027))\r\n", "\tDROP TABLE #tmp_dm_io_virtual_file_stats;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_io_virtual_file_stats\u0027))\t\r\n", "\tCREATE TABLE [dbo].[#tmp_dm_io_virtual_file_stats]\r\n", "\t\t(\r\n", "\t\t\t[retrieval_time] [datetime],\r\n", "\t\t\tdatabase_id int,\r\n", "\t\t\t[file_id] int,\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[logical_file_name] NVARCHAR(255),\r\n", "\t\t\t[type_desc] NVARCHAR(60),\r\n", "\t\t\t[physical_location] NVARCHAR(260),\r\n", "\t\t\t[sample_ms] bigint,\r\n", "\t\t\t[num_of_reads] bigint,\r\n", "\t\t\t[num_of_bytes_read] bigint,\r\n", "\t\t\t[io_stall_read_ms] bigint,\r\n", "\t\t\t[num_of_writes] bigint,\r\n", "\t\t\t[num_of_bytes_written] bigint,\r\n", "\t\t\t[io_stall_write_ms] bigint,\r\n", "\t\t\t[io_stall] bigint,\r\n", "\t\t\t[size_on_disk_bytes] bigint,\r\n", "\t\t\tCONSTRAINT PK_dm_io_virtual_file_stats PRIMARY KEY CLUSTERED(database_id, [file_id], [retrieval_time])\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIOStall\u0027))\r\n", "\tDROP TABLE #tblIOStall;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIOStall\u0027))\r\n", "\tCREATE TABLE #tblIOStall\r\n", "\t\t(\r\n", "\t\t\tdatabase_id int,\r\n", "\t\t\t[file_id] int,\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[logical_file_name] NVARCHAR(255),\r\n", "\t\t\t[type_desc] NVARCHAR(60),\r\n", "\t\t\t[physical_location] NVARCHAR(260),\r\n", "\t\t\tsize_on_disk_Mbytes int,\r\n", "\t\t\tnum_of_reads bigint,\r\n", "\t\t\tnum_of_writes bigint,\r\n", "\t\t\tnum_of_KBytes_read bigint,\r\n", "\t\t\tnum_of_KBytes_written bigint,\r\n", "\t\t\tio_stall_ms int,\r\n", "\t\t\tio_stall_read_ms int,\r\n", "\t\t\tio_stall_write_ms int,\r\n", "\t\t\tavg_read_latency_ms int,\r\n", "\t\t\tavg_write_latency_ms int,\r\n", "\t\t\tavg_io_stall_read_pct int,\r\n", "\t\t\tcumulative_io_stall_read_pct int,\r\n", "\t\t\tavg_io_stall_write_pct int,\r\n", "\t\t\tcumulative_io_stall_write_pct int,\r\n", "\t\t\tcumulative_sample_HH int,\r\n", "\t\t\tio_stall_pct_of_cumulative_sample int,\r\n", "\t\t\tCONSTRAINT PK_IOStall PRIMARY KEY CLUSTERED(database_id, [file_id])\r\n", "\t\t);\r\n", "\t\tSELECT @mincol = GETDATE()\r\n", "\t\tINSERT INTO #tmp_dm_io_virtual_file_stats\r\n", "\t\tSELECT @mincol, f.database_id, f.[file_id], DB_NAME(f.database_id), f.name AS logical_file_name, f.type_desc,\r\n", "\t\t\tCAST (CASE \r\n", "\t\t-- Handle UNC paths (e.g. \u0027\\\\fileserver\\1readonlydbs\\dept_dw.ndf\u0027)\r\n", "\t\t\tWHEN LEFT (LTRIM (f.physical_name), 2) = \u0027\\\\\u0027 \r\n", "\t\t\t\tTHEN LEFT (LTRIM (f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name), 3) + 1) - 1)\r\n", "\t\t\t-- Handle local paths (e.g. \u0027C:\\Program Files\\...\\master.mdf\u0027) \r\n", "\t\t\t\tWHEN CHARINDEX(\u0027\\\u0027, LTRIM(f.physical_name), 3) > 0 \r\n", "\t\t\t\tTHEN UPPER(LEFT(LTRIM(f.physical_name), CHARINDEX (\u0027\\\u0027, LTRIM(f.physical_name), 3) - 1))\r\n", "\t\t\tELSE f.physical_name\r\n", "\t\tEND AS NVARCHAR(255)) AS physical_location,\r\n", "\t\t\tfs.[sample_ms], fs.[num_of_reads], fs.[num_of_bytes_read], fs.[io_stall_read_ms], fs.[num_of_writes],\r\n", "\t\t\tfs.[num_of_bytes_written], fs.[io_stall_write_ms], fs.[io_stall], fs.[size_on_disk_bytes]\r\n", "\t\tFROM sys.dm_io_virtual_file_stats (default, default) AS fs\r\n", "\t\t\tINNER JOIN sys.master_files AS f ON fs.database_id = f.database_id AND fs.[file_id] = f.[file_id]\r\n", "\t\tWAITFOR DELAY \u002700:00:05\u0027\r\n", "\t-- wait 5s between pooling\r\n", "\t\tSELECT @maxcol = GETDATE()\r\n", "\t\tINSERT INTO #tmp_dm_io_virtual_file_stats\r\n", "\t\tSELECT @maxcol, f.database_id, f.[file_id], DB_NAME(f.database_id), f.name AS logical_file_name, f.type_desc,\r\n", "\t\t\tCAST (CASE \r\n", "\t\t-- Handle UNC paths (e.g. \u0027\\\\fileserver\\1readonlydbs\\dept_dw.ndf\u0027)\r\n", "\t\t\tWHEN LEFT (LTRIM (f.physical_name), 2) = \u0027\\\\\u0027 \r\n", "\t\t\t\tTHEN LEFT (LTRIM (f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name), 3) + 1) - 1)\r\n", "\t\t\t-- Handle local paths (e.g. \u0027C:\\Program Files\\...\\master.mdf\u0027) \r\n", "\t\t\t\tWHEN CHARINDEX(\u0027\\\u0027, LTRIM(f.physical_name), 3) > 0 \r\n", "\t\t\t\tTHEN UPPER(LEFT(LTRIM(f.physical_name), CHARINDEX (\u0027\\\u0027, LTRIM(f.physical_name), 3) - 1))\r\n", "\t\t\tELSE f.physical_name\r\n", "\t\tEND AS NVARCHAR(255)) AS physical_location,\r\n", "\t\t\tfs.[sample_ms], fs.[num_of_reads], fs.[num_of_bytes_read], fs.[io_stall_read_ms], fs.[num_of_writes],\r\n", "\t\t\tfs.[num_of_bytes_written], fs.[io_stall_write_ms], fs.[io_stall], fs.[size_on_disk_bytes]\r\n", "\t\tFROM sys.dm_io_virtual_file_stats (default, default) AS fs\r\n", "\t\t\tINNER JOIN sys.master_files AS f ON fs.database_id = f.database_id AND fs.[file_id] = f.[file_id]\r\n", "\t\t;WITH\r\n", "\t\t\tcteFileStats1\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT database_id, [file_id], [DBName], [logical_file_name], [type_desc],\r\n", "\t\t\t\t\t[physical_location], [sample_ms], [num_of_reads], [num_of_bytes_read], [io_stall_read_ms], [num_of_writes],\r\n", "\t\t\t\t\t[num_of_bytes_written], [io_stall_write_ms], [io_stall], [size_on_disk_bytes]\r\n", "\t\t\t\tFROM #tmp_dm_io_virtual_file_stats\r\n", "\t\t\t\tWHERE [retrieval_time] = @mincol\r\n", "\t\t\t),\r\n", "\t\t\tcteFileStats2\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT database_id, [file_id], [DBName], [logical_file_name], [type_desc],\r\n", "\t\t\t\t\t[physical_location], [sample_ms], [num_of_reads], [num_of_bytes_read], [io_stall_read_ms], [num_of_writes],\r\n", "\t\t\t\t\t[num_of_bytes_written], [io_stall_write_ms], [io_stall], [size_on_disk_bytes]\r\n", "\t\t\t\tFROM #tmp_dm_io_virtual_file_stats\r\n", "\t\t\t\tWHERE [retrieval_time] = @maxcol\r\n", "\t\t\t)\r\n", "\t\tINSERT INTO #tblIOStall\r\n", "\t\tSELECT t1.database_id, t1.[file_id], t1.[DBName], t1.logical_file_name, t1.type_desc, t1.physical_location,\r\n", "\t\t\tt1.size_on_disk_bytes/1024/1024 AS size_on_disk_Mbytes,\r\n", "\t\t\t(t2.num_of_reads-t1.num_of_reads) AS num_of_reads,\r\n", "\t\t\t(t2.num_of_writes-t1.num_of_writes) AS num_of_writes,\r\n", "\t\t\t(t2.num_of_bytes_read-t1.num_of_bytes_read)/1024 AS num_of_KBytes_read,\r\n", "\t\t\t(t2.num_of_bytes_written-t1.num_of_bytes_written)/1024 AS num_of_KBytes_written,\r\n", "\t\t\t(t2.io_stall-t1.io_stall) AS io_stall_ms,\r\n", "\t\t\t(t2.io_stall_read_ms-t1.io_stall_read_ms) AS io_stall_read_ms,\r\n", "\t\t\t(t2.io_stall_write_ms-t1.io_stall_write_ms) AS io_stall_write_ms,\r\n", "\t\t\t((t2.io_stall_read_ms-t1.io_stall_read_ms) / (1.0 + (t2.num_of_reads-t1.num_of_reads))) AS avg_read_latency_ms,\r\n", "\t\t\t((t2.io_stall_write_ms-t1.io_stall_write_ms) / (1.0 + (t2.num_of_writes-t1.num_of_writes))) AS avg_write_latency_ms,\r\n", "\t\t\t((t2.io_stall_read_ms - t1.io_stall_read_ms) * 100.) / (CASE WHEN (t2.io_stall - t1.io_stall) <= 0 THEN 1 ELSE (t2.io_stall - t1.io_stall) END) AS avg_io_stall_read_pct,\r\n", "\t\t\t((t2.io_stall_read_ms)*100)/(CASE WHEN t2.io_stall = 0 THEN 1 ELSE t2.io_stall END) AS cumulative_io_stall_read_pct,\r\n", "\t\t\t((t2.io_stall_write_ms - t1.io_stall_write_ms) * 100.) / (CASE WHEN (t2.io_stall - t1.io_stall) <= 0 THEN 1 ELSE (t2.io_stall - t1.io_stall) END) AS avg_io_stall_write_pct,\r\n", "\t\t\t((t2.io_stall_write_ms)*100)/(CASE WHEN t2.io_stall = 0 THEN 1 ELSE t2.io_stall END) AS cumulative_io_stall_write_pct,\r\n", "\t\t\tABS((t2.sample_ms/1000)/60/60) AS cumulative_sample_HH,\r\n", "\t\t\t((t2.io_stall/1000/60)*100)/(ABS((t2.sample_ms/1000)/60)) AS io_stall_pct_of_cumulative_sample\r\n", "\t\tFROM cteFileStats1 t1 INNER JOIN cteFileStats2 t2 ON t1.database_id = t2.database_id AND t1.[file_id] = t2.[file_id]\r\n", "\t\tIF (SELECT COUNT([logical_file_name])\r\n", "\t\t\tFROM #tblIOStall\r\n", "\t\t\tWHERE avg_read_latency_ms >= 20) > 0\r\n", "\t\t\tOR (SELECT COUNT([logical_file_name])\r\n", "\t\t\tFROM #tblIOStall\r\n", "\t\t\tWHERE avg_write_latency_ms >= 20) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Check], \u0027[WARNING: Some database files have latencies >= 20ms in the last 5s. Review I/O related performance counters and storage-related configurations.]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Information], [DBName] AS [Database_Name], [logical_file_name], [type_desc], avg_read_latency_ms, avg_write_latency_ms,\r\n", "\t\t\t\t[physical_location], size_on_disk_Mbytes, num_of_reads AS physical_reads, num_of_writes AS physical_writes,\r\n", "\t\t\t\tnum_of_KBytes_read, num_of_KBytes_written, io_stall_ms, io_stall_read_ms, io_stall_write_ms,\r\n", "\t\t\t\tavg_io_stall_read_pct, cumulative_io_stall_read_pct, avg_io_stall_write_pct, cumulative_io_stall_write_pct, cumulative_sample_HH, io_stall_pct_of_cumulative_sample\r\n", "\t\t\tFROM #tblIOStall\r\n", "\t\t\tWHERE avg_read_latency_ms >= 20 OR avg_write_latency_ms >= 20\r\n", "\t\t\tORDER BY avg_read_latency_ms DESC, avg_write_latency_ms DESC, [DBName], [type_desc], [logical_file_name]\r\n", "\t\tEND\r\n", "\tELSE IF (SELECT COUNT([logical_file_name])\r\n", "\t\tFROM #tblIOStall\r\n", "\t\tWHERE io_stall_pct_of_cumulative_sample > 50) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Check], \u0027[WARNING: Some database files have stall I/O exceeding 50 pct of cumulative sampled time. Review I/O related performance counters and storage-related configurations.]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Information], [DBName] AS [Database_Name], [logical_file_name], [type_desc], avg_read_latency_ms, avg_write_latency_ms,\r\n", "\t\t\t\t[physical_location], size_on_disk_Mbytes, num_of_reads AS physical_reads, num_of_writes AS physical_writes,\r\n", "\t\t\t\tnum_of_KBytes_read, num_of_KBytes_written, io_stall_ms, io_stall_read_ms, io_stall_write_ms,\r\n", "\t\t\t\tavg_io_stall_read_pct, cumulative_io_stall_read_pct, avg_io_stall_write_pct, cumulative_io_stall_write_pct, cumulative_sample_HH, io_stall_pct_of_cumulative_sample\r\n", "\t\t\tFROM #tblIOStall\r\n", "\t\t\tWHERE io_stall_pct_of_cumulative_sample > 50\r\n", "\t\t\tORDER BY io_stall_pct_of_cumulative_sample DESC, [DBName], [type_desc], [logical_file_name]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t/*SELECT \u0027IO_checks\u0027 AS [Category], \u0027Stalled_IO\u0027 AS [Information], [DBName] AS [Database_Name], [logical_file_name], [type_desc], avg_read_latency_ms, avg_write_latency_ms, \r\n", "\t\t\t[physical_location], size_on_disk_Mbytes, num_of_reads AS physical_reads, num_of_writes AS physical_writes, \r\n", "\t\t\tnum_of_KBytes_read, num_of_KBytes_written, io_stall_ms, io_stall_read_ms, io_stall_write_ms,\r\n", "\t\t\tavg_io_stall_read_pct, cumulative_io_stall_read_pct, avg_io_stall_write_pct, cumulative_io_stall_write_pct, cumulative_sample_HH, io_stall_pct_of_cumulative_sample\r\n", "\t\tFROM #tblIOStall\r\n", "\t\tORDER BY [DBName], [type_desc], [logical_file_name]*/\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "97171802-cdc8-41db-a430-d40cdea3132d", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Pending disk I/O Requests subsection \r\n", "- Indicate that your I/O has insufficient service capabilities (HBA queue depths, reduced throughput, etc).\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "3c6b35c3-bbdd-473a-a348-1cbce293c58b" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Pending disk I/O Requests subsection (wait for a max of 5s)\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE @IOCnt tinyint\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIOReq\u0027))\r\n", "\tDROP TABLE #tblPendingIOReq;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIOReq\u0027))\r\n", "\tCREATE TABLE #tblPendingIOReq\r\n", "\t\t(\r\n", "\t\t\tio_completion_request_address varbinary(8),\r\n", "\t\t\tio_handle varbinary(8),\r\n", "\t\t\tio_type VARCHAR(7),\r\n", "\t\t\tio_pending bigint,\r\n", "\t\t\tio_pending_ms_ticks bigint,\r\n", "\t\t\tscheduler_address varbinary(8)\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIO\u0027))\r\n", "\tDROP TABLE #tblPendingIO;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIO\u0027))\r\n", "\tCREATE TABLE #tblPendingIO\r\n", "\t\t(\r\n", "\t\t\tdatabase_id int,\r\n", "\t\t\t[file_id] int,\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[logical_file_name] NVARCHAR(255),\r\n", "\t\t\t[type_desc] NVARCHAR(60),\r\n", "\t\t\t[physical_location] NVARCHAR(260),\r\n", "\t\t\tio_stall_min int,\r\n", "\t\t\tio_stall_read_min int,\r\n", "\t\t\tio_stall_write_min int,\r\n", "\t\t\tavg_read_latency_ms int,\r\n", "\t\t\tavg_write_latency_ms int,\r\n", "\t\t\tio_stall_read_pct int,\r\n", "\t\t\tio_stall_write_pct int,\r\n", "\t\t\tsampled_HH int,\r\n", "\t\t\tio_stall_pct_of_overall_sample int,\r\n", "\t\t\tio_completion_request_address varbinary(8),\r\n", "\t\t\tio_handle varbinary(8),\r\n", "\t\t\tio_type VARCHAR(7),\r\n", "\t\t\tio_pending bigint,\r\n", "\t\t\tio_pending_ms_ticks bigint,\r\n", "\t\t\tscheduler_address varbinary(8),\r\n", "\t\t\tscheduler_id int,\r\n", "\t\t\tpending_disk_io_count int,\r\n", "\t\t\twork_queue_count bigint\r\n", "\t\t);\r\n", "\t\tSET @IOCnt = 1\r\n", "\t\tWHILE @IOCnt < 5\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblPendingIOReq\r\n", "\t\t\tSELECT io_completion_request_address, io_handle, io_type, io_pending, io_pending_ms_ticks, scheduler_address\r\n", "\t\t\tFROM sys.dm_io_pending_io_requests;\r\n", "\t\t\tIF (SELECT COUNT(io_pending)\r\n", "\t\t\tFROM #tblPendingIOReq\r\n", "\t\t\tWHERE io_type = \u0027disk\u0027) > 1\r\n", "\t\tBREAK\r\n", "\t\t\tWAITFOR DELAY \u002700:00:01\u0027\r\n", "\t\t-- wait 1s between pooling\r\n", "\t\t\tSET @IOCnt = @IOCnt + 1\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(io_pending)\r\n", "\t\tFROM #tblPendingIOReq\r\n", "\t\tWHERE io_type = \u0027disk\u0027) > 0\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblPendingIO\r\n", "\t\t\tSELECT DISTINCT f.database_id, f.[file_id], DB_NAME(f.database_id) AS database_name, f.name AS logical_file_name, f.type_desc,\r\n", "\t\t\t\tCAST (CASE \r\n", "\t\t\t-- Handle UNC paths (e.g. \u0027\\\\fileserver\\1readonlydbs\\dept_dw.ndf\u0027)\r\n", "\t\t\t\tWHEN LEFT (LTRIM (f.physical_name), 2) = \u0027\\\\\u0027 \r\n", "\t\t\t\t\tTHEN LEFT (LTRIM (f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name),CHARINDEX(\u0027\\\u0027,LTRIM(f.physical_name), 3) + 1) - 1)\r\n", "\t\t\t\t-- Handle local paths (e.g. \u0027C:\\Program Files\\...\\master.mdf\u0027) \r\n", "\t\t\t\t\tWHEN CHARINDEX(\u0027\\\u0027, LTRIM(f.physical_name), 3) > 0 \r\n", "\t\t\t\t\tTHEN UPPER(LEFT(LTRIM(f.physical_name), CHARINDEX (\u0027\\\u0027, LTRIM(f.physical_name), 3) - 1))\r\n", "\t\t\t\tELSE f.physical_name\r\n", "\t\t\tEND AS NVARCHAR(255)) AS physical_location,\r\n", "\t\t\t\tfs.io_stall/1000/60 AS io_stall_min,\r\n", "\t\t\t\tfs.io_stall_read_ms/1000/60 AS io_stall_read_min,\r\n", "\t\t\t\tfs.io_stall_write_ms/1000/60 AS io_stall_write_min,\r\n", "\t\t\t\t(fs.io_stall_read_ms / (1.0 + fs.num_of_reads)) AS avg_read_latency_ms,\r\n", "\t\t\t\t(fs.io_stall_write_ms / (1.0 + fs.num_of_writes)) AS avg_write_latency_ms,\r\n", "\t\t\t\t((fs.io_stall_read_ms/1000/60)*100)/(CASE WHEN fs.io_stall/1000/60 = 0 THEN 1 ELSE fs.io_stall/1000/60 END) AS io_stall_read_pct,\r\n", "\t\t\t\t((fs.io_stall_write_ms/1000/60)*100)/(CASE WHEN fs.io_stall/1000/60 = 0 THEN 1 ELSE fs.io_stall/1000/60 END) AS io_stall_write_pct,\r\n", "\t\t\t\tABS((fs.sample_ms/1000)/60/60) AS \u0027sample_HH\u0027,\r\n", "\t\t\t\t((fs.io_stall/1000/60)*100)/(ABS((fs.sample_ms/1000)/60))AS \u0027io_stall_pct_of_overall_sample\u0027,\r\n", "\t\t\t\tpio.io_completion_request_address, pio.io_handle, pio.io_type, pio.io_pending,\r\n", "\t\t\t\tpio.io_pending_ms_ticks, pio.scheduler_address, os.scheduler_id, os.pending_disk_io_count, os.work_queue_count\r\n", "\t\t\tFROM #tblPendingIOReq AS pio\r\n", "\t\t\t\tINNER JOIN sys.dm_io_virtual_file_stats (NULL,NULL) AS fs ON fs.file_handle = pio.io_handle\r\n", "\t\t\t\tINNER JOIN sys.dm_os_schedulers AS os ON pio.scheduler_address = os.scheduler_address\r\n", "\t\t\t\tINNER JOIN sys.master_files AS f ON fs.database_id = f.database_id AND fs.[file_id] = f.[file_id];\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(io_pending)\r\n", "\t\tFROM #tblPendingIOReq\r\n", "\t\tWHERE io_type = \u0027disk\u0027) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Pending_IO\u0027 AS [Check], \u0027[WARNING: Pending disk I/O requests were found. Review I/O related performance counters and storage-related configurations]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Pending_IO\u0027 AS [Information], [DBName] AS [Database_Name], [logical_file_name], [type_desc], avg_read_latency_ms, avg_write_latency_ms,\r\n", "\t\t\t\tio_stall_read_pct, io_stall_write_pct, sampled_HH, io_stall_pct_of_overall_sample, [physical_location], io_stall_min, io_stall_read_min, io_stall_write_min,\r\n", "\t\t\t\tio_completion_request_address, io_type, CASE WHEN io_pending = 1 THEN \u0027Pending_Context_Switching\u0027 ELSE \u0027Pending_WindowsOS\u0027 END AS io_pending_type,\r\n", "\t\t\t\tio_pending_ms_ticks, scheduler_address, scheduler_id, pending_disk_io_count, work_queue_count\r\n", "\t\t\tFROM #tblPendingIO\r\n", "\t\t\tORDER BY scheduler_address, [DBName], [type_desc], [logical_file_name]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027IO_checks\u0027 AS [Category], \u0027Pending_IO\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Server Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "a26041e2-cc05-4ab2-ad8a-8ded8c6630da", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--## Server Checks section\r\n" ], "metadata": { "azdata_cell_guid": "6bf2a8d5-d155-4a0b-85fa-1149e5a1c7aa" } }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Power plan subsection\r\n" ], "metadata": { "azdata_cell_guid": "a75e2198-13a1-4132-ae4d-1360e9031dda" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Power plan\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @planguid NVARCHAR(64), @powerkey1 NVARCHAR(255), @powerkey2 NVARCHAR(255)\r\n", "--SELECT @powerkey = \u0027SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\{025A5937-A6BE-4686-A844-36FE4BEC8B6D}\u0027\r\n", "--SELECT @powerkey = \u0027SYSTEM\\CurrentControlSet\\Control\\Power\\User\\Default\\PowerSchemes\u0027\r\n", "\tSELECT @powerkey1 = \u0027SOFTWARE\\Policies\\Microsoft\\Power\\PowerSettings\u0027\r\n", "\tSELECT @powerkey2 = \u0027SYSTEM\\CurrentControlSet\\Control\\Power\\User\\PowerSchemes\u0027\r\n", "\tIF CONVERT(DECIMAL(3,1), @osver) >= 6.0\r\n", "BEGIN\r\n", "\t\tBEGIN TRY\r\n", "\t-- Check if was set by GPO, if not, look in user settings \r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @powerkey1, \u0027ActivePowerScheme\u0027, @planguid OUTPUT, NO_OUTPUT\r\n", "\t\tIF @planguid IS NULL \r\n", "\t\tBEGIN\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @powerkey2, \u0027ActivePowerScheme\u0027, @planguid OUTPUT, NO_OUTPUT\r\n", "\t\tEND \r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Power plan subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tEND\r\n", "-- http://support.microsoft.com/kb/935799/en-us\r\n", "\tIF @osver IS NULL \r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Current_Power_Plan\u0027 AS [Check], \u0027[WARNING: Could not determine Windows version for check]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE IF @planguid IS NOT NULL AND @planguid <> N\u00278c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\u0027\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Current_Power_Plan\u0027 AS [Check], \u0027[WARNING: The current power plan scheme is not recommended for database servers. Please reconfigure for High Performance mode]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Current_Power_Plan\u0027 AS [Information], CASE WHEN @planguid = N\u0027381b4222-f694-41f0-9685-ff5bb260df2e\u0027 THEN \u0027Balanced\u0027\r\n", "\t\tWHEN @planguid = N\u00278c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\u0027 THEN \u0027High Performance\u0027\r\n", "\t\tWHEN @planguid = N\u0027a1841308-3541-4fab-bc81-f71556f20b4a\u0027 THEN \u0027Power Saver\u0027\r\n", "\t\tELSE \u0027Other\u0027 END AS [Power_Plan]\r\n", "\tEND\r\n", "ELSE IF @planguid IS NOT NULL AND @planguid = \u00278c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\u0027\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Current_Power_Plan\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "95228af7-73b8-4fe8-b4ad-8811805fd320", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Disk Partition alignment offset < 64KB subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "- If not, default location for .ps1 files is the Log folder.\r\n" ], "metadata": { "azdata_cell_guid": "9044d966-c9ce-429f-a863-0fdd3e11627c" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Disk Partition alignment offset < 64KB\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @ostype <> \u0027Windows\u0027\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"partition alignment offset\" check was skipped: not Windows OS.]\u0027, 10, 1, N\u0027not_windows\u0027)\r\n", "--RETURN\r\n", "\tEND\r\n", "ELSE IF @ostype = \u0027Windows\u0027 AND @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", "BEGIN\r\n", "\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\tFROM sys.credentials\r\n", "\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", "\t\t\tAND (SELECT COUNT(l.name)\r\n", "\t\t\tFROM sys.server_permissions p JOIN sys.server_principals l\r\n", "\t\t\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\t\t\tAND l.is_disabled = 0\r\n", "\t\t\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\t\t\tAND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_fileexist\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OAGetErrorInfo\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OACreate\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OADestroy\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regenumvalues\u0027) > 0)))\r\n", "\tBEGIN\r\n", "\t\t\tDECLARE @diskpart int\r\n", "\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\tSELECT @ole = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", "\t\t\tRAISERROR (\u0027 |-Configuration options set for Disk partition alignment offset check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @ole = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tDECLARE @output_hw_tot_diskpart TABLE ([PS_OUTPUT] VARCHAR(2048));\r\n", "\t\t\tDECLARE @output_hw_format_diskpart TABLE ([volid] smallint IDENTITY(1,1),\r\n", "\t\t\t\t[HD_Partition] VARCHAR(50) NULL,\r\n", "\t\t\t\tStartingOffset bigint NULL)\r\n", "\t\t\tIF @custompath IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027,N\u0027Software\\Microsoft\\MSSQLServer\\Setup\u0027,N\u0027SQLPath\u0027, @path OUTPUT\r\n", "\t\t\t\t\tSET @path = @path + \u0027\\LOG\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @sqlcmd = N\u0027SELECT @pathOUT = LEFT([path], LEN([path])-1) FROM sys.dm_os_server_diagnostics_log_configurations\u0027;\r\n", "\t\t\t\t\tSET @params = N\u0027@pathOUT NVARCHAR(2048) OUTPUT\u0027;\r\n", "\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @pathOUT=@path OUTPUT;\r\n", "\t\t\t\tEND\r\n", "\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FSO OUT\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FSO, \u0027FolderExists\u0027, @existout OUT, @path\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling FolderExists Method 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tIF @existout <> 1\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tSET @path = CONVERT(NVARCHAR(500), SERVERPROPERTY(\u0027ErrorLogFileName\u0027))\r\n", "\t\t\t\t\t\t\tSET @path = LEFT(@path,LEN(@path)-CHARINDEX(\u0027\\\u0027, REVERSE(@path)))\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FSO\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @path = CASE WHEN @custompath LIKE \u0027%\\\u0027 THEN LEFT(@custompath, LEN(@custompath)-1) ELSE @custompath END\r\n", "\t\t\tEND\r\n", "\t\t\tSET @FileName = @path + \u0027\\checkbp_diskpart_\u0027 + RTRIM(@server) + \u0027.ps1\u0027\r\n", "\t\t\tEXEC master.dbo.xp_fileexist @FileName, @existout out\r\n", "\t\t\tIF @existout = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t-- Scan for local disks\r\n", "\t\t\t\tSET @Text1 = \u0027[string] $serverName = \u0027\u0027localhost\u0027\u0027\r\n", "$partitions = Get-WmiObject -computername $serverName -query \"SELECT * FROM Win32_DiskPartition\"\r\n", "foreach ($partition in $partitions)\r\n", "{\r\n", "[string] $diskpart = \"{0}_{1};{2}\" -f $partition.DiskIndex,$partition.Index,$partition.StartingOffset\r\n", "Write-Output $diskpart\r\n", "}\r\n", "\u0027\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FS OUT\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\t--Open file\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FS, \u0027OpenTextFile\u0027, @FileID OUT, @FileName, 2, 1\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling OpenTextFile Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not create file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Created file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tEND\r\n", "\t\t\t--Write Text1\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FileID, \u0027WriteLine\u0027, NULL, @Text1\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling WriteLine Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not write to file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tEXEC @OLEResult = sp_OADestroy @FileID\r\n", "\t\t\t\tEXEC @OLEResult = sp_OADestroy @FS\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027 |-Reusing file \u0027 + @FileName\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\tEND\r\n", "\t\t\tIF @psver = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile -File \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\tEND;\r\n", "\t\t\tINSERT INTO @output_hw_tot_diskpart\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD\r\n", "\t\t\tSET @CMD = \u0027del /Q \"\u0027 + @FileName + \u0027\"\u0027\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD, NO_OUTPUT\r\n", "\t\t\tINSERT INTO @output_hw_format_diskpart\r\n", "\t\t\t\t([HD_Partition],StartingOffset)\r\n", "\t\t\tSELECT LEFT(RTRIM([PS_OUTPUT]), CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT]))-1 END),\r\n", "\t\t\t\tRIGHT(RTRIM([PS_OUTPUT]), LEN(RTRIM([PS_OUTPUT]))-CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) END)\r\n", "\t\t\tFROM @output_hw_tot_diskpart\r\n", "\t\t\tWHERE [PS_OUTPUT] IS NOT NULL;\r\n", "\t\t\tSET @CMD2 = \u0027del \u0027 + @FileName\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD2, NO_OUTPUT;\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @ole = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND;\r\n", "\t\t\t\t\t\r\n", "\t\t;\r\n", "\t\t\tWITH\r\n", "\t\t\t\tdiskpartcte (StartingOffset)\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT StartingOffset\r\n", "\t\t\t\t\tFROM @output_hw_format_diskpart\r\n", "\t\t\t\t\tWHERE StartingOffset IS NOT NULL OR LEN(StartingOffset) > 0\r\n", "\t\t\t\t)\r\n", "\t\t\tSELECT @diskpart = CASE WHEN (SELECT COUNT(*)\r\n", "\t\t\t\tFROM diskpartcte) = 0 THEN NULL ELSE COUNT(cte1.[StartingOffset]) END\r\n", "\t\t\tFROM diskpartcte cte1\r\n", "\t\t\tWHERE cte1.[StartingOffset] < 65536;\r\n", "\t\t\tIF @diskpart > 0 AND @diskpart IS NOT NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Partition_Alignment\u0027 AS [Check], \u0027[WARNING: Some disk partitions are not using a minimum recommended alignment offset of 64KB]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Partition_Alignment\u0027 AS [Information], LEFT(t1.[HD_Partition],LEN(t1.[HD_Partition])-CHARINDEX(\u0027_\u0027,t1.[HD_Partition])) AS HD_Volume,\r\n", "\t\t\t\t\tRIGHT(t1.[HD_Partition],LEN(t1.[HD_Partition])-CHARINDEX(\u0027_\u0027,t1.[HD_Partition])) AS [HD_Partition],\r\n", "\t\t\t\t\t(t1.StartingOffset/1024) AS [StartingOffset_KB]\r\n", "\t\t\t\tFROM @output_hw_format_diskpart t1\r\n", "\t\t\t\tWHERE t1.StartingOffset IS NOT NULL OR LEN(t1.StartingOffset) > 0\r\n", "\t\t\t\tORDER BY t1.[HD_Partition]\r\n", "\t\t\t\tOPTION\r\n", "\t\t\t\t(RECOMPILE);\r\n", "\t\t\tEND\r\n", "\t\tELSE IF @diskpart IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Partition_Alignment\u0027 AS [Check], \u0027[WARNING: Could not gather information on disk partition offset size]\u0027 AS [Deviation]\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Partition_Alignment\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"partition alignment offset\" checks. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_cmdshell, xp_instance_regread, xp_regread, xp_fileexist and xp_regenumvalues. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"partition alignment offset\" check was skipped: either xp_cmdshell or execution of PS scripts was not allowed.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "f0a9247f-04c3-40b9-8115-524697e2a8a4", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### NTFS block size in volumes that hold database files <> 64KB subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "- If not, default location for .ps1 files is the Log folder.\r\n" ], "metadata": { "azdata_cell_guid": "22a3318b-62ea-4a6e-95f8-a465ece9e697" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting NTFS block size in volumes that hold database files <> 64KB\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @ostype <> \u0027Windows\u0027\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"NTFS block size\" check was skipped: not Windows OS.]\u0027, 10, 1, N\u0027not_windows\u0027)\r\n", "--RETURN\r\n", "\tEND\r\n", "ELSE IF @ostype = \u0027Windows\u0027 AND @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", "BEGIN\r\n", "\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\tFROM sys.credentials\r\n", "\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", "\t\t\tAND (SELECT COUNT(l.name)\r\n", "\t\t\tFROM sys.server_permissions p JOIN sys.server_principals l\r\n", "\t\t\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\t\t\tAND l.is_disabled = 0\r\n", "\t\t\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\t\t\tAND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_fileexist\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OAGetErrorInfo\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OACreate\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OADestroy\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regenumvalues\u0027) > 0)))\r\n", "\tBEGIN\r\n", "\t\t\tDECLARE @ntfs int\r\n", "\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\tSELECT @ole = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", "\t\t\tRAISERROR (\u0027 |-Configuration options set for NTFS Block size check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @ole = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tDECLARE @output_hw_tot_ntfs TABLE ([PS_OUTPUT] VARCHAR(2048));\r\n", "\t\t\tDECLARE @output_hw_format_ntfs TABLE ([volid] smallint IDENTITY(1,1),\r\n", "\t\t\t\t[HD_Volume] NVARCHAR(2048) NULL,\r\n", "\t\t\t\t[NTFS_Block] NVARCHAR(8) NULL)\r\n", "\t\t\tIF @custompath IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027,N\u0027Software\\Microsoft\\MSSQLServer\\Setup\u0027,N\u0027SQLPath\u0027, @path OUTPUT\r\n", "\t\t\t\t\tSET @path = @path + \u0027\\LOG\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @sqlcmd = N\u0027SELECT @pathOUT = LEFT([path], LEN([path])-1) FROM sys.dm_os_server_diagnostics_log_configurations\u0027;\r\n", "\t\t\t\t\tSET @params = N\u0027@pathOUT NVARCHAR(2048) OUTPUT\u0027;\r\n", "\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @pathOUT=@path OUTPUT;\r\n", "\t\t\t\tEND\r\n", "\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FSO OUT\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FSO, \u0027FolderExists\u0027, @existout OUT, @path\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling FolderExists Method 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tIF @existout <> 1\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tSET @path = CONVERT(NVARCHAR(500), SERVERPROPERTY(\u0027ErrorLogFileName\u0027))\r\n", "\t\t\t\t\t\t\tSET @path = LEFT(@path,LEN(@path)-CHARINDEX(\u0027\\\u0027, REVERSE(@path)))\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FSO\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @path = CASE WHEN @custompath LIKE \u0027%\\\u0027 THEN LEFT(@custompath, LEN(@custompath)-1) ELSE @custompath END\r\n", "\t\t\tEND\r\n", "\t\t\tSET @FileName = @path + \u0027\\checkbp_ntfs_\u0027 + RTRIM(@server) + \u0027.ps1\u0027\r\n", "\t\t\tEXEC master.dbo.xp_fileexist @FileName, @existout out\r\n", "\t\t\tIF @existout = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t-- Scan for local disks\r\n", "\t\t\t\tSET @Text1 = \u0027[string] $serverName = \u0027\u0027localhost\u0027\u0027\r\n", "$vols = Get-WmiObject -computername $serverName -query \"select name, blocksize from Win32_Volume where Capacity <> NULL and DriveType = 3\"\r\n", "foreach($vol in $vols)\r\n", "{\r\n", "[string] $drive = \"{0};{1}\" -f $vol.name,$vol.blocksize\r\n", "Write-Output $drive\r\n", "} \u0027\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FS OUT\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\t--Open file\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FS, \u0027OpenTextFile\u0027, @FileID OUT, @FileName, 2, 1\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling OpenTextFile Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not create file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Created file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tEND\r\n", "\t\t\t--Write Text1\r\n", "\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FileID, \u0027WriteLine\u0027, NULL, @Text1\r\n", "\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling WriteLine Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not write to file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tEXEC @OLEResult = sp_OADestroy @FileID\r\n", "\t\t\t\tEXEC @OLEResult = sp_OADestroy @FS\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027 |-Reusing file \u0027 + @FileName\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\tEND\r\n", "\t\t\tIF @psver = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile -File \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\tEND;\r\n", "\t\t\tINSERT INTO @output_hw_tot_ntfs\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD\r\n", "\t\t\tSET @CMD = \u0027del /Q \"\u0027 + @FileName + \u0027\"\u0027\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD, NO_OUTPUT\r\n", "\t\t\tINSERT INTO @output_hw_format_ntfs\r\n", "\t\t\t\t([HD_Volume],[NTFS_Block])\r\n", "\t\t\tSELECT LEFT(RTRIM([PS_OUTPUT]), CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT]))-1 END),\r\n", "\t\t\t\tRIGHT(RTRIM([PS_OUTPUT]), LEN(RTRIM([PS_OUTPUT]))-CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) END)\r\n", "\t\t\tFROM @output_hw_tot_ntfs\r\n", "\t\t\tWHERE [PS_OUTPUT] IS NOT NULL;\r\n", "\t\t\tSET @CMD2 = \u0027del \u0027 + @FileName\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD2, NO_OUTPUT;\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @ole = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND;\r\n", "\t\t\tWITH\r\n", "\t\t\t\tntfscte (physical_name, ntfsblock)\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT DISTINCT(LEFT(physical_name, LEN(t2.HD_Volume))), [NTFS_Block]\r\n", "\t\t\t\t\tFROM sys.master_files t1 INNER JOIN @output_hw_format_ntfs t2\r\n", "\t\t\t\t\t\tON LEFT(physical_name, LEN(t2.HD_Volume)) = t2.HD_Volume\r\n", "\t\t\t\t\tWHERE [database_id] <> 32767 AND (t2.[NTFS_Block] IS NOT NULL OR LEN(t2.[NTFS_Block]) > 0)\r\n", "\t\t\t\t)\r\n", "\t\t\tSELECT @ntfs = CASE WHEN (SELECT COUNT(*)\r\n", "\t\t\t\tFROM ntfscte) = 0 THEN NULL ELSE COUNT(cte1.[ntfsblock]) END\r\n", "\t\t\tFROM ntfscte cte1\r\n", "\t\t\tWHERE cte1.[ntfsblock] <> 65536;\r\n", "\t\t\tIF @ntfs > 0 AND @ntfs IS NOT NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027NTFS_Block_Size\u0027 AS [Check], \u0027[WARNING: Some volumes that hold database files are not formatted using the recommended NTFS block size of 64KB]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027NTFS_Block_Size\u0027 AS [Information], t1.HD_Volume, (t1.[NTFS_Block]/1024) AS [NTFS_Block_Size_KB]\r\n", "\t\t\t\tFROM (SELECT DISTINCT(LEFT(physical_name, LEN(t2.HD_Volume))) AS [HD_Volume], [NTFS_Block]\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format_ntfs t2\r\n", "\t\t\t\t\t\tON LEFT(physical_name, LEN(t2.HD_Volume)) = t2.HD_Volume\r\n", "\t\t\t\t\tWHERE [database_id] <> 32767 AND (t2.[NTFS_Block] IS NOT NULL OR LEN(t2.[NTFS_Block]) > 0)) t1\r\n", "\t\t\t\tORDER BY t1.HD_Volume\r\n", "\t\t\t\tOPTION\r\n", "\t\t\t\t(RECOMPILE);\r\n", "\t\t\tEND\r\n", "\t\tELSE IF @ntfs IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027NTFS_Block_Size\u0027 AS [Check], \u0027[WARNING: Could not gather information on NTFS block size]\u0027 AS [Deviation]\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027NTFS_Block_Size\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"NTFS block size\" checks. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_cmdshell, xp_instance_regread, xp_regread, xp_fileexist and xp_regenumvalues. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"NTFS block size\" check was skipped: either xp_cmdshell or execution of PS scripts was not allowed.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "658c83e7-339b-41d5-8aaf-4ec84c5ca0f8", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Disk Fragmentation Analysis subsection \r\n", "You can set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--\t- Can take some time in large disks. Requires elevated privileges. \r\n", "--\t- See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives \r\n", "- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "- If not, default location for .ps1 files is the Log folder.\r\n" ], "metadata": { "azdata_cell_guid": "feab26b1-52d9-457c-82aa-dfc637e5b44e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @diskfrag = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Disk Fragmentation Analysis\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @ostype <> \u0027Windows\u0027\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Disk Fragmentation Analysis\" check was skipped: not Windows OS.]\u0027, 10, 1, N\u0027not_windows\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tELSE IF @ostype = \u0027Windows\u0027 AND @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", "\tBEGIN\r\n", "\t\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\t\tFROM sys.credentials\r\n", "\t\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", "\t\t\t\tAND (SELECT COUNT(l.name)\r\n", "\t\t\t\tFROM sys.server_permissions p JOIN sys.server_principals l\r\n", "\t\t\t\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\t\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\t\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\t\t\t\tAND l.is_disabled = 0\r\n", "\t\t\t\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\t\t\t\tAND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND ((SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_fileexist\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OAGetErrorInfo\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OACreate\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OADestroy\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_regenumvalues\u0027) > 0)))\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @frag int\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tSELECT @ole = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for Disk Fragmentation Analysis\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tDECLARE @output_hw_frag TABLE ([PS_OUTPUT] VARCHAR(2048));\r\n", "\t\t\t\tDECLARE @output_hw_format_frag TABLE ([volid] smallint IDENTITY(1,1),\r\n", "\t\t\t\t\t[volfrag] VARCHAR(255),\r\n", "\t\t\t\t\t[fragrec] VARCHAR(10) NULL)\r\n", "\t\t\t\tIF @custompath IS NULL\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027,N\u0027Software\\Microsoft\\MSSQLServer\\Setup\u0027,N\u0027SQLPath\u0027, @path OUTPUT\r\n", "\t\t\t\t\t\tSET @path = @path + \u0027\\LOG\u0027\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @sqlcmd = N\u0027SELECT @pathOUT = LEFT([path], LEN([path])-1) FROM sys.dm_os_server_diagnostics_log_configurations\u0027;\r\n", "\t\t\t\t\t\tSET @params = N\u0027@pathOUT NVARCHAR(2048) OUTPUT\u0027;\r\n", "\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @pathOUT=@path OUTPUT;\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FSO OUT\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FSO, \u0027FolderExists\u0027, @existout OUT, @path\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling FolderExists Method 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tIF @existout <> 1\r\n", "\t\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\tSET @path = CONVERT(NVARCHAR(500), SERVERPROPERTY(\u0027ErrorLogFileName\u0027))\r\n", "\t\t\t\t\t\t\t\tSET @path = LEFT(@path,LEN(@path)-CHARINDEX(\u0027\\\u0027, REVERSE(@path)))\r\n", "\t\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FSO\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @path = CASE WHEN @custompath LIKE \u0027%\\\u0027 THEN LEFT(@custompath, LEN(@custompath)-1) ELSE @custompath END\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tSET @FileName = @path + \u0027\\checkbp_frag_\u0027 + RTRIM(@server) + \u0027.ps1\u0027\r\n", "\t\t\t\tEXEC master.dbo.xp_fileexist @FileName, @existout out\r\n", "\t\t\t\tIF @existout = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t-- Scan for frag\r\n", "\t\t\t\t\tSET @Text1 = \u0027$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n", "$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)\r\n", "$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator\r\n", "if ($myWindowsPrincipal.IsInRole($adminRole))\r\n", "{\r\n", "\t[string] $serverName = \u0027\u0027localhost\u0027\u0027\r\n", "\t$DiskResults = @()\r\n", "\t$objDisks = Get-WmiObject -Computername $serverName -Class Win32_Volume | Where-Object { $_.DriveType -eq 3 -and $_.Name -like \"*:\\\"}\r\n", "\tForEach( $disk in $objDisks)\r\n", "\t{\r\n", "\t\t$objDefrag = $disk.DefragAnalysis()\r\n", "\t\t$rec = $objDefrag.DefragRecommended\r\n", "\t\t$objDefragDetail = $objDefrag.DefragAnalysis\r\n", "\t\t$diskFragmentation = $objDefragDetail.TotalPercentFragmentation\r\n", "\t\t$FreeFragmentation = $objDefragDetail.FreeSpacePercentFragmentation\r\n", "\t\t$FileFragmentation = $objDefragDetail.FilePercentFragmentation\r\n", "\t\t[string] $ThisVolume = \"{0}TotalFragPct {1} :: FreeSpaceFragPct {2} :: FileFragPct {3};{4}\" -f $($disk.Name),$diskFragmentation,$FreeFragmentation,$FileFragmentation,$rec\r\n", "\t\t$DiskResults += $ThisVolume\r\n", "\t}\r\n", "\t$DiskResults\r\n", "}\r\n", "else\r\n", "{\r\n", "\tWrite-Host \"NotAdmin\"\r\n", "}\r\n", "\u0027\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FS OUT\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t--Open file\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FS, \u0027OpenTextFile\u0027, @FileID OUT, @FileName, 2, 1\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling OpenTextFile Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not create file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Created file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t--Write Text1\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FileID, \u0027WriteLine\u0027, NULL, @Text1\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling WriteLine Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not write to file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FileID\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FS\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Reusing file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tRAISERROR (\u0027 |-Getting Disk(s) Fragmentation. This may take some time...\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @psver = 1\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile -File \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tINSERT INTO @output_hw_frag\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD\r\n", "\t\t\t\tSET @CMD = \u0027del /Q \"\u0027 + @FileName + \u0027\"\u0027\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD, NO_OUTPUT\r\n", "\t\t\t\tIF (SELECT COUNT([PS_OUTPUT])\r\n", "\t\t\t\tFROM @output_hw_frag\r\n", "\t\t\t\tWHERE [PS_OUTPUT] LIKE \u0027%NotAdmin%\u0027) = 1\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tRAISERROR (\u0027[WARNING: Powershell not running under Elevated Privileges. Bypassing Disk Fragmentation Analysis]\u0027,16,1);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tINSERT INTO @output_hw_format_frag\r\n", "\t\t\t\t\t\t([volfrag],fragrec)\r\n", "\t\t\t\t\tSELECT LEFT(RTRIM([PS_OUTPUT]), CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT]))-1 END),\r\n", "\t\t\t\t\t\tRIGHT(RTRIM([PS_OUTPUT]), LEN(RTRIM([PS_OUTPUT]))-CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) END)\r\n", "\t\t\t\t\tFROM @output_hw_frag\r\n", "\t\t\t\t\tWHERE [PS_OUTPUT] IS NOT NULL\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tSET @CMD2 = \u0027del \u0027 + @FileName\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD2, NO_OUTPUT;\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND;\r\n", "\t\t\t;\r\n", "\t\t\t\tWITH\r\n", "\t\t\t\t\tfragcte (fragrec)\r\n", "\t\t\t\t\tAS\r\n", "\t\t\t\t\t(\r\n", "\t\t\t\t\t\tSELECT fragrec\r\n", "\t\t\t\t\t\tFROM @output_hw_format_frag\r\n", "\t\t\t\t\t\tWHERE fragrec IS NOT NULL OR LEN(fragrec) > 0\r\n", "\t\t\t\t\t)\r\n", "\t\t\t\tSELECT @frag = CASE WHEN (SELECT COUNT(*)\r\n", "\t\t\t\t\tFROM fragcte) = 0 THEN NULL ELSE COUNT(cte1.[fragrec]) END\r\n", "\t\t\t\tFROM fragcte cte1\r\n", "\t\t\t\tWHERE cte1.[fragrec] = \u0027True\u0027;\r\n", "\t\t\t\tIF @frag > 0 AND @frag IS NOT NULL\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Disk_Fragmentation\u0027 AS [Check], \u0027[WARNING: Found volumes with physical fragmentation. Determine how and when these can be defragmented]\u0027 AS [Deviation]\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Disk_Fragmentation\u0027 AS [Information],\r\n", "\t\t\t\t\t\tLEFT(t1.[volfrag],1) AS HD_Volume,\r\n", "\t\t\t\t\t\tRIGHT(t1.[volfrag],(LEN(t1.[volfrag])-3)) AS [Fragmentation_Percent],\r\n", "\t\t\t\t\t\tt1.fragrec AS [Defragmentation_Recommended]\r\n", "\t\t\t\t\tFROM @output_hw_format_frag t1\r\n", "\t\t\t\t\tWHERE t1.fragrec = \u0027True\u0027\r\n", "\t\t\t\t\tORDER BY t1.[volfrag]\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE IF @frag IS NULL\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Disk_Fragmentation\u0027 AS [Check], \u0027[WARNING: Could not gather information on Disk Fragmentation Analysis]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Disk_Fragmentation\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Disk_Fragmentation\u0027 AS [Information],\r\n", "\t\t\t\t\t\tLEFT(t1.[volfrag],1) AS HD_Volume,\r\n", "\t\t\t\t\t\tRIGHT(t1.[volfrag],(LEN(t1.[volfrag])-3)) AS [Fragmentation_Percent],\r\n", "\t\t\t\t\t\tt1.fragrec AS [Defragmentation_Recommended]\r\n", "\t\t\t\t\tFROM @output_hw_format_frag t1\r\n", "\t\t\t\t\tORDER BY t1.[volfrag]\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Disk Fragmentation Analysis\" checks. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_cmdshell, xp_instance_regread, xp_regread, xp_fileexist and xp_regenumvalues. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t\t--RETURN\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Disk Fragmentation Analysis\" check was skipped: either xp_cmdshell or execution of PS scripts was not allowed]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"Disk Fragmentation Analysis\" check is disabled]\u0027, 10, 1, N\u0027disallow_diskfrag\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "0861b6f8-3411-4e74-9077-da508005a469", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Cluster Quorum Model subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n" ], "metadata": { "azdata_cell_guid": "f730d322-11df-4d04-8709-8304c25b1409" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @clustered = 1 AND @osver <> \u00275.2\u0027\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Cluster Quorum Model\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027)) AND @psver > 1\r\n", "\tBEGIN\r\n", "\t\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\t\tFROM sys.credentials\r\n", "\t\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0)) -- Is not sysadmin but proxy account exists\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0))\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for Cluster Quorum Model check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tDECLARE /*@CMD NVARCHAR(4000), @line int, @linemax int, */ @CntNodes tinyint, @CntVotes tinyint\r\n", "\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluNodesOutput\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_CluNodesOutput;\r\n", "\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluNodesOutput\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_CluNodesOutput\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tline int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\t\t\t[Output] VARCHAR(50)\r\n", "\t\t\t\t);\r\n", "\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluOutput\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_CluOutput;\r\n", "\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluOutput\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_CluOutput\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tline int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\t\t\t[Output] VARCHAR(50)\r\n", "\t\t\t\t);\r\n", "\t\t\t\tIF @osver <> \u00275.2\u0027\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @CMD = N\u0027powershell -NoLogo -NoProfile \"Import-Module FailoverClusters\"; \"Get-ClusterNode | Format-Table -Autosize -HideTableHeaders NodeWeight\"\u0027\r\n", "\t\t\t\t\tINSERT INTO #xp_cmdshell_CluNodesOutput\r\n", "\t\t\t\t\t\t([Output])\r\n", "\t\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tSELECT @CMD = N\u0027powershell -NoLogo -NoProfile \"Import-Module FailoverClusters\"; \"Get-ClusterQuorum | Format-Table -Autosize -HideTableHeaders QuorumType\"\u0027\r\n", "\t\t\t\tINSERT INTO #xp_cmdshell_CluOutput\r\n", "\t\t\t\t\t([Output])\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\t\tIF (SELECT COUNT([Output])\r\n", "\t\t\t\tFROM #xp_cmdshell_CluNodesOutput\r\n", "\t\t\t\tWHERE [Output] = \u0027\u0027) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @CntNodes = COUNT(NodeName)\r\n", "\t\t\t\t\tFROM sys.dm_os_cluster_nodes (NOLOCK)\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_Quorum\u0027 AS [Check],\r\n", "\t\t\t\t\t\tCASE WHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027DiskOnly\u0027 AND @osver <> \u00275.2\u0027 THEN \u0027[WARNING: The current quorum model is not recommended since WS2003]\u0027\r\n", "\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeAndDiskMajority\u0027 AND @CntNodes % 2 = 1 THEN \u0027[WARNING: The current quorum model is not recommended for a cluster with ODD number of nodes]\u0027\r\n", "\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeMajority\u0027 AND @CntNodes % 2 = 0 THEN \u0027[WARNING: The current quorum model is not recommended for a cluster with EVEN number of nodes]\u0027\r\n", "\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeAndFileShareMajority\u0027 THEN \u0027[INFORMATION: The current quorum model is recommended for clusters with special configurations]\u0027\r\n", "\t\t\t\t\t\tELSE \u0027[OK]\u0027 END AS [Deviation],\r\n", "\t\t\t\t\t\tQUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027)) AS QuorumModel,\r\n", "\t\t\t\t\t\t\u0027[WARNING: No count of votes available, using count of nodes instead. Check if KB2494036 applies and is installed]\u0027 AS [Comment]\r\n", "\t\t\t\t-- http://support.microsoft.com/kb/2494036\r\n", "\t\t\t\t\tFROM #xp_cmdshell_CluOutput\r\n", "\t\t\t\t\tWHERE [Output] IS NOT NULL\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @CntVotes = SUM(CONVERT(int, [Output]))\r\n", "\t\t\t\t\tFROM #xp_cmdshell_CluNodesOutput\r\n", "\t\t\t\t\tWHERE [Output] IS NOT NULL\r\n", "\t\t\t\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\t\t\t\t[Output]\r\n", "\t\t\t\t\tFROM #xp_cmdshell_CluOutput\r\n", "\t\t\t\t\tWHERE [Output] LIKE \u0027%Majority%\u0027 OR [Output] LIKE \u0027%Disk%\u0027)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_Quorum\u0027 AS [Check],\r\n", "\t\t\t\t\t\t\tCASE WHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027DiskOnly\u0027 AND @osver <> \u00275.2\u0027 THEN \u0027[WARNING: The current quorum model is not recommended since WS2003]\u0027\r\n", "\t\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeAndDiskMajority\u0027 AND @CntVotes % 2 = 1 THEN \u0027[WARNING: The current quorum model is not recommended for a cluster with ODD number of node votes]\u0027\r\n", "\t\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeMajority\u0027 AND @CntVotes % 2 = 0 THEN \u0027[WARNING: The current quorum model is not recommended for a cluster with EVEN number of node votes]\u0027\r\n", "\t\t\t\t\t\t\tWHEN REPLACE([Output], CHAR(9), \u0027\u0027) = \u0027NodeAndFileShareMajority\u0027 THEN \u0027[INFORMATION: The current quorum model is recommended for clusters with special configurations]\u0027\r\n", "\t\t\t\t\t\t\tELSE \u0027[OK]\u0027 END AS [Deviation],\r\n", "\t\t\t\t\t\t\tQUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027)) AS QuorumModel\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_CluOutput\r\n", "\t\t\t\t\t\tWHERE [Output] IS NOT NULL\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Cluster Quorum Model\" check. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: xp_cmdshell. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t\t--RETURN\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE IF @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027)) AND @psver = 1\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Cluster Quorum Model\" check was skipped: cannot execute with PS v1]\u0027, 10, 1, N\u0027disallow_ps\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Cluster Quorum Model\" check was skipped: either xp_cmdshell or execution of PS scripts was not allowed]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_Quorum\u0027 AS [Check], \u0027NOT_CLUSTERED\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF @IsHadrEnabled = 1\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd\t= N\u0027DECLARE @osver VARCHAR(5), @CntNodes tinyint\r\n", "SELECT @osver = windows_release FROM sys.dm_os_windows_info (NOLOCK)\t\r\n", "SELECT @CntNodes = SUM(number_of_quorum_votes) FROM sys.dm_hadr_cluster_members (NOLOCK)\r\n", "SELECT \u0027\u0027Server_checks\u0027\u0027 AS [Category], \u0027\u0027AlwaysOn_Cluster_Quorum\u0027\u0027 AS [Check], cluster_name,\r\n", "\tCASE WHEN quorum_type = 3 AND @osver <> \u0027\u00275.2\u0027\u0027 THEN \u0027\u0027[WARNING: The current quorum model is not recommended since WS2003]\u0027\u0027\r\n", "\t\tWHEN quorum_type = 1 AND @CntNodes % 2 = 1 THEN \u0027\u0027[WARNING: The current quorum model is not recommended for a cluster with ODD number of nodes]\u0027\u0027\r\n", "\t\tWHEN quorum_type = 0 AND @CntNodes % 2 = 0 THEN \u0027\u0027[WARNING: The current quorum model is not recommended for a cluster with EVEN number of nodes]\u0027\u0027\r\n", "\t\tWHEN quorum_type = 2 THEN \u0027\u0027[INFORMATION: The current quorum model is recommended for clusters with special configurations]\u0027\u0027\r\n", "\t\tELSE \u0027\u0027[OK]\u0027\u0027 END AS [Deviation], \r\n", "\tQUOTENAME(quorum_type_desc) AS QuorumModel\r\n", "FROM sys.dm_hadr_cluster;\u0027\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND;\r\n", "\tIF @sqlmajorver >= 13 AND @IsHadrEnabled = 1\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd\t= N\u0027IF EXISTS (SELECT 1 FROM sys.availability_groups where db_failover = 0) \r\n", "\tSELECT \u0027\u0027Server_checks\u0027\u0027 AS [Category], \u0027\u0027AlwaysOn_Replica_Cluster_Database_Health_Detection\u0027\u0027 AS [Information], \u0027\u0027[INFORMATION: Consider enabling Database Health Detection]\u0027\u0027\r\n", "\tSELECT \u0027\u0027Server_checks\u0027\u0027 AS [Category], \u0027\u0027AlwaysOn_Replica_Cluster_Database_Health_Detection\u0027\u0027 AS [Information], name, failure_condition_level, db_failover \r\n", "\tFROM sys.availability_groups where db_failover = 0;\u0027\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "16af029b-a18c-45be-ad0b-e046dcaa6c75", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Cluster NIC Binding order subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "- If not, default location for .ps1 files is the Log folder.\r\n" ], "metadata": { "azdata_cell_guid": "cc11e464-060a-461e-9c76-63bbf13eaa86" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @allow_xpcmdshell = 1 and @clustered = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Cluster NIC Binding order\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @allow_xpcmdshell = 1 AND (@psavail IS NOT NULL AND @psavail IN (\u0027RemoteSigned\u0027,\u0027Unrestricted\u0027))\r\n", "\tBEGIN\r\n", "\t\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\t\tFROM sys.credentials\r\n", "\t\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", "\t\t\t\tAND (SELECT COUNT(l.name)\r\n", "\t\t\t\tFROM sys.server_permissions p JOIN sys.server_principals l\r\n", "\t\t\t\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\t\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\t\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\t\t\t\tAND l.is_disabled = 0\r\n", "\t\t\t\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\t\t\t\tAND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND ((SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_fileexist\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OAGetErrorInfo\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OACreate\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027sp_OADestroy\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0 AND\r\n", "\t\t\t\t(SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_regenumvalues\u0027) > 0)))\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @clunic int, @maxnic int\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tSELECT @ole = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for Cluster NIC Binding Order check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tDECLARE @output_hw_nics TABLE ([PS_OUTPUT] VARCHAR(2048));\r\n", "\t\t\t\tDECLARE @output_hw_format_nics TABLE ([nicid] smallint,\r\n", "\t\t\t\t\t[nicname] VARCHAR(255) NULL)\r\n", "\t\t\t\tIF @custompath IS NULL\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027,N\u0027Software\\Microsoft\\MSSQLServer\\Setup\u0027,N\u0027SQLPath\u0027, @path OUTPUT\r\n", "\t\t\t\t\t\tSET @path = @path + \u0027\\LOG\u0027\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @sqlcmd = N\u0027SELECT @pathOUT = LEFT([path], LEN([path])-1) FROM sys.dm_os_server_diagnostics_log_configurations\u0027;\r\n", "\t\t\t\t\t\tSET @params = N\u0027@pathOUT NVARCHAR(2048) OUTPUT\u0027;\r\n", "\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @pathOUT=@path OUTPUT;\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FSO OUT\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FSO, \u0027FolderExists\u0027, @existout OUT, @path\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling FolderExists Method 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tIF @existout <> 1\r\n", "\t\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\tSET @path = CONVERT(NVARCHAR(500), SERVERPROPERTY(\u0027ErrorLogFileName\u0027))\r\n", "\t\t\t\t\t\t\t\tSET @path = LEFT(@path,LEN(@path)-CHARINDEX(\u0027\\\u0027, REVERSE(@path)))\r\n", "\t\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FSO\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @path = CASE WHEN @custompath LIKE \u0027%\\\u0027 THEN LEFT(@custompath, LEN(@custompath)-1) ELSE @custompath END\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tSET @FileName = @path + \u0027\\checkbp_nics_\u0027 + RTRIM(@server) + \u0027.ps1\u0027\r\n", "\t\t\t\tEXEC master.dbo.xp_fileexist @FileName, @existout out\r\n", "\t\t\t\tIF @existout = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t-- Scan for nics\r\n", "\t\t\t\t\tSET @Text1 = \u0027[string] $serverName = \u0027\u0027localhost\u0027\u0027\r\n", "$nics = Get-WmiObject -Computername $serverName -query \"SELECT Description, Index FROM Win32_NetworkAdapterConfiguration\"\r\n", "foreach ($nic in $nics)\r\n", "{\r\n", "[string] $allnics = \"{0};{1}\" -f $nic.Index,$nic.Description\r\n", "Write-Output $allnics\r\n", "}\r\n", "\u0027\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FS OUT\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t--Open file\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FS, \u0027OpenTextFile\u0027, @FileID OUT, @FileName, 2, 1\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling OpenTextFile Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not create file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Created file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t--Write Text1\r\n", "\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FileID, \u0027WriteLine\u0027, NULL, @Text1\r\n", "\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling WriteLine Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not write to file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FileID\r\n", "\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FS\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Reusing file \u0027 + @FileName\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @psver = 1\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile -File \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tINSERT INTO @output_hw_nics\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD\r\n", "\t\t\t\tSET @CMD = \u0027del /Q \"\u0027 + @FileName + \u0027\"\u0027\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD, NO_OUTPUT\r\n", "\t\t\t\tINSERT INTO @output_hw_format_nics\r\n", "\t\t\t\t\t([nicid],nicname)\r\n", "\t\t\t\tSELECT LEFT(RTRIM([PS_OUTPUT]), CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT]))-1 END),\r\n", "\t\t\t\t\tRIGHT(RTRIM([PS_OUTPUT]), LEN(RTRIM([PS_OUTPUT]))-CASE WHEN CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) = 0 THEN LEN(RTRIM([PS_OUTPUT])) ELSE CHARINDEX(\u0027;\u0027, RTRIM([PS_OUTPUT])) END)\r\n", "\t\t\t\tFROM @output_hw_nics\r\n", "\t\t\t\tWHERE [PS_OUTPUT] IS NOT NULL;\r\n", "\t\t\t\tSET @CMD2 = \u0027del \u0027 + @FileName\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD2, NO_OUTPUT;\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tSELECT @maxnic = MAX(nicid)\r\n", "\t\t\t\tFROM @output_hw_format_nics;\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@clunic = nicid\r\n", "\t\t\t\tFROM @output_hw_format_nics\r\n", "\t\t\t\tWHERE nicname LIKE \u0027%Cluster Virtual Adapter%\u0027;\r\n", "\t\t\t\tIF @clunic < @maxnic OR @clunic IS NULL --http://support2.microsoft.com/kb/955963\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_NIC_Binding\u0027 AS [Check], \u0027[WARNING: The Microsoft Failover Cluster Virtual Adapter is not in the correct binding order. Should be the lowest of all present NICs]\u0027 AS [Deviation]\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_NIC_Binding\u0027 AS [Information], nicid AS NIC_ID, nicname AS NIC_Name\r\n", "\t\t\t\t\tFROM @output_hw_format_nics t1\r\n", "\t\t\t\t\tORDER BY t1.[nicid]\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE IF @clunic = @maxnic\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_NIC_Binding\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_NIC_Binding\u0027 AS [Check], \u0027[WARNING: Could not gather information on NIC binding order]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Cluster NIC Binding Order\" checks. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_cmdshell, xp_instance_regread, xp_regread, xp_fileexist and xp_regenumvalues. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t\t--RETURN\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Cluster NIC Binding Order\" check was skipped: either xp_cmdshell or execution of PS scripts was not allowed.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_NIC_Binding\u0027 AS [Check], \u0027NOT_CLUSTERED\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "5d6fdf73-12f2-493c-bd1c-741601b08f1f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Cluster QFE node equality subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n" ], "metadata": { "azdata_cell_guid": "26f62df1-d092-45d7-8096-ffec49299ee5" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @clustered = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting QFE node equality\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @allow_xpcmdshell = 1\r\n", "\tBEGIN\r\n", "\t\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\t\tFROM sys.credentials\r\n", "\t\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0)) -- Is not sysadmin but proxy account exists\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0))\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for QFE node equality check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tDECLARE /* @CMD NVARCHAR(4000), @line int, @linemax int, */ @Node VARCHAR(50)\r\n", "\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_Nodes\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_Nodes;\r\n", "\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_Nodes\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_Nodes\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tNodeName VARCHAR(50),\r\n", "\t\t\t\t\tisdone bit NOT NULL\r\n", "\t\t\t\t);\r\n", "\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEOutput\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_QFEOutput;\r\n", "\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEOutput\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_QFEOutput\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tline int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\t\t\t[Output] VARCHAR(150)\r\n", "\t\t\t\t);\r\n", "\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEFinal\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_QFEFinal;\r\n", "\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEFinal\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_QFEFinal\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tNodeName VARCHAR(50),\r\n", "\t\t\t\t\t[QFE] VARCHAR(150)\r\n", "\t\t\t\t);\r\n", "\t\t\t\tINSERT INTO #xp_cmdshell_Nodes\r\n", "\t\t\t\tSELECT NodeName, 0\r\n", "\t\t\t\tFROM sys.dm_os_cluster_nodes (NOLOCK);\r\n", "\t\t\t\tWHILE (SELECT COUNT(NodeName)\r\n", "\t\t\t\tFROM #xp_cmdshell_Nodes\r\n", "\t\t\t\tWHERE isdone = 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t\t@Node = NodeName\r\n", "\t\t\t\t\tFROM #xp_cmdshell_Nodes\r\n", "\t\t\t\t\tWHERE isdone = 0;\r\n", "\t\t\t\t\tSET @CMD = \u0027wmic /node:\"\u0027 + @Node + \u0027\" qfe get hotfixid\u0027\r\n", "\t\t\t\t\tINSERT INTO #xp_cmdshell_QFEOutput\r\n", "\t\t\t\t\t\t([Output])\r\n", "\t\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\t\t\tIF (SELECT COUNT([Output])\r\n", "\t\t\t\t\tFROM #xp_cmdshell_QFEOutput\r\n", "\t\t\t\t\tWHERE [Output] LIKE \u0027%Access is denied%\u0027) = 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tINSERT INTO #xp_cmdshell_QFEFinal\r\n", "\t\t\t\t\t\tSELECT @Node, RTRIM(REPLACE([Output],CHAR(13),\u0027\u0027))\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_QFEOutput\r\n", "\t\t\t\t\t\tWHERE RTRIM(REPLACE([Output],CHAR(13),\u0027\u0027)) NOT IN (\u0027\u0027,\u0027HotFixID\u0027);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @ErrorMessage = \u0027[WARNING: Access Denied error while trying to get updates from node \u0027 + @Node + \u0027]\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage,16,1);\r\n", "\t\t\t\t\tEND;\r\n", "\t\t\t\t\tTRUNCATE TABLE #xp_cmdshell_QFEOutput;\r\n", "\t\t\t\t\tUPDATE #xp_cmdshell_Nodes \r\n", "\t\t\t\tSET isdone = 1\r\n", "\t\t\t\tWHERE NodeName = @Node;\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tIF (SELECT COUNT(DISTINCT NodeName)\r\n", "\t\t\t\tFROM #xp_cmdshell_QFEFinal) = (SELECT COUNT(DISTINCT NodeName)\r\n", "\t\t\t\tFROM #xp_cmdshell_Nodes)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\t\tFROM #xp_cmdshell_QFEFinal t1\r\n", "\t\t\t\t\tWHERE t1.[QFE] NOT IN (SELECT DISTINCT t2.[QFE]\r\n", "\t\t\t\t\tFROM #xp_cmdshell_QFEFinal t2\r\n", "\t\t\t\t\tWHERE t2.NodeName <> t1.NodeName)) > 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_QFE_Equality\u0027 AS [Check], \u0027[WARNING: Missing updates found in some of the nodes]\u0027 AS [Deviation]\r\n", "\t\t\t\t\t\tSELECT t1.NodeName, t1.[QFE] AS MissingUpdates\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_QFEFinal t1\r\n", "\t\t\t\t\t\tWHERE t1.[QFE] NOT IN (SELECT DISTINCT t2.[QFE]\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_QFEFinal t2\r\n", "\t\t\t\t\t\tWHERE t2.NodeName <> t1.NodeName);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_QFE_Equality\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\t\t\t\t\tSELECT DISTINCT t1.[QFE] AS InstalledUpdates\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_QFEFinal t1;\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tRAISERROR (\u0027[WARNING: Could not collect data from all cluster nodes. Bypassing QFE node equality check]\u0027,16,1);\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"QFE node equality\" check. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: xp_cmdshell. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t\t--RETURN\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"QFE node equality\" check was skipped because xp_cmdshell was not allowed.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Server_checks\u0027 AS [Category], \u0027Cluster_QFE_Equality\u0027 AS [Check], \u0027NOT_CLUSTERED\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Service Accounts Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "e46f5de9-24e4-4e07-af40-ca48b93804a9", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Service Accounts Status subsection\r\n" ], "metadata": { "azdata_cell_guid": "1e16de30-524f-4b26-891f-f1e51b35bbc2" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Service Accounts Status\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1)\r\n", "\t\tOR ((SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_regread\u0027) = 1 AND\r\n", "\t\t(SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_servicecontrol\u0027) = 1)\r\n", "BEGIN\r\n", "\t\tDECLARE @rc int, @profile NVARCHAR(128)\r\n", "\t\tDECLARE @sqlservice NVARCHAR(128), @sqlagentservice NVARCHAR(128), @dtsservice NVARCHAR(128), @ftservice NVARCHAR(128)\r\n", "\t\tDECLARE @browservice NVARCHAR(128), @olapservice NVARCHAR(128), @rsservice NVARCHAR(128)\r\n", "\t\tDECLARE @statussqlservice NVARCHAR(20), @statussqlagentservice NVARCHAR(20), @statusdtsservice NVARCHAR(20), @statusftservice NVARCHAR(20)\r\n", "\t\tDECLARE @statusbrowservice NVARCHAR(20), @statusolapservice NVARCHAR(20), @statusrsservice NVARCHAR(20)\r\n", "\t\tDECLARE @regkeysqlservice NVARCHAR(256), @regkeysqlagentservice NVARCHAR(256), @regkeydtsservice NVARCHAR(256), @regkeyftservice NVARCHAR(256)\r\n", "\t\tDECLARE @regkeybrowservice NVARCHAR(256), @regkeyolapservice NVARCHAR(256), @regkeyrsservice NVARCHAR(256)\r\n", "\t\tDECLARE @accntsqlagentservice NVARCHAR(128), @accntdtsservice NVARCHAR(128), @accntftservice NVARCHAR(128)\r\n", "\t\tDECLARE @accntbrowservice NVARCHAR(128), @accntolapservice NVARCHAR(128), @accntrsservice NVARCHAR(128)\r\n", "\t-- Get service names\r\n", "\t\tIF (@instancename IS NULL) \r\n", "\tBEGIN\r\n", "\t\t\tIF @sqlmajorver < 11\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @sqlservice = N\u0027MSSQLServer\u0027\r\n", "\t\t\t\tSELECT @sqlagentservice = N\u0027SQLServerAgent\u0027\r\n", "\t\t\tEND\r\n", "\t\t\tSELECT @olapservice = N\u0027MSSQLServerOLAPService\u0027\r\n", "\t\t\tSELECT @rsservice = N\u0027ReportServer\u0027\r\n", "\t\tEND \r\n", "\tELSE \r\n", "\tBEGIN\r\n", "\t\t\tIF @sqlmajorver < 11\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @sqlservice = N\u0027MSSQL$\u0027 + @instancename\r\n", "\t\t\t\tSELECT @sqlagentservice = N\u0027SQLAgent$\u0027 + @instancename\r\n", "\t\t\tEND\r\n", "\t\t\tSELECT @olapservice = N\u0027MSOLAP$\u0027 + @instancename\r\n", "\t\t\tSELECT @rsservice = N\u0027ReportServer$\u0027 + @instancename\r\n", "\t\tEND\r\n", "\t\tIF @sqlmajorver = 9\r\n", "\tBEGIN\r\n", "\t\t\tSELECT @dtsservice = N\u0027MsDtsServer\u0027\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT @dtsservice = N\u0027MsDtsServer\u0027 + CONVERT(VARCHAR, @sqlmajorver) + \u00270\u0027\r\n", "\t\tEND\r\n", "\t\tIF (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 1\r\n", "\tBEGIN\r\n", "\t\t\tIF (@instancename IS NULL) AND @sqlmajorver = 10\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ftservice = N\u0027MSSQLFDLauncher\u0027\r\n", "\t\t\tEND \r\n", "\t\tELSE IF (@instancename IS NOT NULL) AND @sqlmajorver = 10\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ftservice = N\u0027MSSQLFDLauncher$\u0027 + @instancename\r\n", "\t\t\tEND\r\n", "\t\tELSE IF (@instancename IS NULL) AND @sqlmajorver = 9\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ftservice = N\u0027msftesql\u0027\r\n", "\t\t\tEND\r\n", "\t\tELSE IF (@instancename IS NOT NULL) AND @sqlmajorver = 9 \r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ftservice = N\u0027msftesql$\u0027 + @instancename\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tSELECT @browservice = N\u0027SQLBrowser\u0027\r\n", "\t\tIF @sqlmajorver < 11\r\n", "\tBEGIN\r\n", "\t\t\tSELECT @regkeysqlservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @sqlservice\r\n", "\t\t\tSELECT @regkeysqlagentservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @sqlagentservice\r\n", "\t\t\tIF (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @regkeyftservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @ftservice\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tSELECT @regkeyolapservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @olapservice\r\n", "\t\tSELECT @regkeyrsservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @rsservice\r\n", "\t\tSELECT @regkeydtsservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @dtsservice\r\n", "\t\tSELECT @regkeybrowservice = N\u0027SYSTEM\\CurrentControlSet\\Services\\\u0027 + @browservice\r\n", "\t-- Service status\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#RegResult\u0027))\r\n", "\tCREATE TABLE #RegResult\r\n", "\t\t(\r\n", "\t\t\tResultValue bit\r\n", "\t\t)\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#ServiceStatus\u0027))\r\n", "\tCREATE TABLE #ServiceStatus\r\n", "\t\t(\r\n", "\t\t\tServiceStatus VARCHAR(128)\r\n", "\t\t)\r\n", "\t\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #RegResult\r\n", "\t\t\t\t(ResultValue)\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeysqlservice\r\n", "\t\t\tIF (SELECT TOP 1\r\n", "\t\t\t\tResultValue\r\n", "\t\t\tFROM #RegResult) = 1 \r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t\t(ServiceStatus)\r\n", "\t\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @sqlservice\r\n", "\t\t\t\tSELECT @statussqlservice = ServiceStatus\r\n", "\t\t\t\tFROM #ServiceStatus\r\n", "\t\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSET @statussqlservice = \u0027Not Installed\u0027\r\n", "\t\t\tEND\r\n", "\t\t\tTRUNCATE TABLE #RegResult;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 1. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @statussqlserviceOUT = status_desc FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Server%\u0027\u0027 AND servicename NOT LIKE \u0027\u0027SQL Server Agent%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@statussqlserviceOUT NVARCHAR(20) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @statussqlserviceOUT=@statussqlservice OUTPUT;\r\n", "\t\t\tIF @statussqlservice IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @statussqlservice = \u0027Not Installed\u0027\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #RegResult\r\n", "\t\t\t\t(ResultValue)\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeysqlagentservice\r\n", "\t\t\tIF (SELECT TOP 1\r\n", "\t\t\t\tResultValue\r\n", "\t\t\tFROM #RegResult) = 1 \r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t\t(ServiceStatus)\r\n", "\t\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @sqlagentservice\r\n", "\t\t\t\tSELECT @statussqlagentservice = ServiceStatus\r\n", "\t\t\t\tFROM #ServiceStatus\r\n", "\t\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSET @statussqlagentservice = \u0027Not Installed\u0027\r\n", "\t\t\tEND\r\n", "\t\t\tTRUNCATE TABLE #RegResult;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 2. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @statussqlagentserviceOUT = status_desc FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Server Agent%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@statussqlagentserviceOUT NVARCHAR(20) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @statussqlagentserviceOUT=@statussqlagentservice OUTPUT;\r\n", "\t\t\tIF @statussqlagentservice IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @statussqlagentservice = \u0027Not Installed\u0027\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "\tBEGIN\r\n", "\t\t\tIF (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #RegResult\r\n", "\t\t\t\t\t(ResultValue)\r\n", "\t\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyftservice\r\n", "\t\t\t\tIF (SELECT TOP 1\r\n", "\t\t\t\t\tResultValue\r\n", "\t\t\t\tFROM #RegResult) = 1 \r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t\t\t(ServiceStatus)\r\n", "\t\t\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @ftservice\r\n", "\t\t\t\t\tSELECT @statusftservice = ServiceStatus\r\n", "\t\t\t\t\tFROM #ServiceStatus\r\n", "\t\t\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @statusftservice = \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tTRUNCATE TABLE #RegResult;\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 3. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @statusftserviceOUT = status_desc FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Full-text Filter Daemon Launcher%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@statusftserviceOUT NVARCHAR(20) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @statusftserviceOUT=@statusftservice OUTPUT;\r\n", "\t\t\tIF @statusftservice IS NULL\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @statusftservice = \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #RegResult\r\n", "\t\t\t(ResultValue)\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyolapservice\r\n", "\t\tIF (SELECT TOP 1\r\n", "\t\t\tResultValue\r\n", "\t\tFROM #RegResult) = 1 \r\n", "\t\tBEGIN\r\n", "\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t(ServiceStatus)\r\n", "\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @olapservice\r\n", "\t\t\tSELECT @statusolapservice = ServiceStatus\r\n", "\t\t\tFROM #ServiceStatus\r\n", "\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @statusolapservice = \u0027Not Installed\u0027\r\n", "\t\tEND\r\n", "\t\tTRUNCATE TABLE #RegResult;\r\n", "\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 4. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #RegResult\r\n", "\t\t\t(ResultValue)\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyrsservice\r\n", "\t\tIF (SELECT TOP 1\r\n", "\t\t\tResultValue\r\n", "\t\tFROM #RegResult) = 1 \r\n", "\t\tBEGIN\r\n", "\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t(ServiceStatus)\r\n", "\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @rsservice\r\n", "\t\t\tSELECT @statusrsservice = ServiceStatus\r\n", "\t\t\tFROM #ServiceStatus\r\n", "\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @statusrsservice = \u0027Not Installed\u0027\r\n", "\t\tEND\r\n", "\t\tTRUNCATE TABLE #RegResult;\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 5. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #RegResult\r\n", "\t\t\t(ResultValue)\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeydtsservice\r\n", "\t\tIF (SELECT TOP 1\r\n", "\t\t\tResultValue\r\n", "\t\tFROM #RegResult) = 1 \r\n", "\t\tBEGIN\r\n", "\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t(ServiceStatus)\r\n", "\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @dtsservice\r\n", "\t\t\tSELECT @statusdtsservice = ServiceStatus\r\n", "\t\t\tFROM #ServiceStatus\r\n", "\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @statusdtsservice = \u0027Not Installed\u0027\r\n", "\t\tEND\r\n", "\t\tTRUNCATE TABLE #RegResult;\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 6. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #RegResult\r\n", "\t\t\t(ResultValue)\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeybrowservice\r\n", "\t\tIF (SELECT TOP 1\r\n", "\t\t\tResultValue\r\n", "\t\tFROM #RegResult) = 1 \r\n", "\t\tBEGIN\r\n", "\t\t\tINSERT INTO #ServiceStatus\r\n", "\t\t\t\t(ServiceStatus)\r\n", "\t\t\tEXEC master.sys.xp_servicecontrol N\u0027QUERYSTATE\u0027, @browservice\r\n", "\t\t\tSELECT @statusbrowservice = ServiceStatus\r\n", "\t\t\tFROM #ServiceStatus\r\n", "\t\t\tTRUNCATE TABLE #ServiceStatus;\r\n", "\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\tSET @statusbrowservice = \u0027Not Installed\u0027\r\n", "\t\tEND\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 7. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tDROP TABLE #RegResult;\r\n", "\t\tDROP TABLE #ServiceStatus;\r\n", "\t-- Accounts\r\n", "\t\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500)\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeysqlservice, N\u0027ObjectName\u0027, @accntsqlservice OUTPUT, NO_OUTPUT\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeysqlagentservice, N\u0027ObjectName\u0027, @accntsqlagentservice OUTPUT, NO_OUTPUT\r\n", "\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyftservice, N\u0027ObjectName\u0027, @accntftservice OUTPUT, NO_OUTPUT\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 8. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @accntsqlserviceOUT = service_account FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Server%\u0027\u0027 AND servicename NOT LIKE \u0027\u0027SQL Server Agent%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@accntsqlserviceOUT NVARCHAR(128) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @accntsqlserviceOUT=@accntsqlservice OUTPUT;\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @accntsqlagentserviceOUT = service_account FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Server Agent%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@accntsqlagentserviceOUT NVARCHAR(128) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @accntsqlagentserviceOUT=@accntsqlagentservice OUTPUT;\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @accntftserviceOUT = service_account FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Full-text Filter Daemon Launcher%\u0027\u0027\u0027;\r\n", "\t\t\tSET @params = N\u0027@accntftserviceOUT NVARCHAR(128) OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @accntftserviceOUT=@accntftservice OUTPUT;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 9. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\t\tBEGIN TRY\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyolapservice, N\u0027ObjectName\u0027, @accntolapservice OUTPUT, NO_OUTPUT\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeyrsservice, N\u0027ObjectName\u0027, @accntrsservice OUTPUT, NO_OUTPUT\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeydtsservice, N\u0027ObjectName\u0027, @accntdtsservice OUTPUT, NO_OUTPUT\r\n", "\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, @regkeybrowservice, N\u0027ObjectName\u0027, @accntbrowservice OUTPUT, NO_OUTPUT\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Service Accounts and Status subsection - Error raised in TRY block 10. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027accntsqlservice\u0027, @accntsqlservice )\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server\u0027 AS [Service], @statussqlservice AS [Status], @accntsqlservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statussqlservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statussqlservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntsqlservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntsqlservice = \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not supported]\u0027\r\n", "\t\t\tWHEN @clustered = 1 AND @accntsqlservice = \u0027NT AUTHORITY\\SYSTEM\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not supported]\u0027 \r\n", "\t\t\tWHEN @clustered = 1 AND @accntsqlservice = \u0027LocalSystem\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not supported]\u0027 \r\n", "\t\t\tWHEN @clustered = 1 AND @accntsqlservice = \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not supported]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @accntsqlservice = \u0027NT AUTHORITY\\SYSTEM\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @accntsqlservice = \u0027LocalSystem\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @accntsqlservice = \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server under this account is not recommended]\u0027\r\n", "\t\t-- MSA for WS2008R2 or higher, SQL Server 2012 or higher, non-clustered (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntsqlservice <> \u0027NT SERVICE\\MSSQLSERVER\u0027 AND @accntsqlservice NOT LIKE \u0027NT SERVICE\\MSSQL$%\u0027 THEN \u0027[INFORMATION: SQL Server is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server_Agent\u0027 AS [Service], @statussqlagentservice AS [Status], @accntsqlagentservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statussqlagentservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statussqlagentservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntsqlagentservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntsqlagentservice = \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server Agent under this account is not supported]\u0027\r\n", "\t\t\tWHEN @accntsqlagentservice = @accntsqlservice THEN \u0027[WARNING: Running SQL Server Agent under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 1 AND @accntsqlagentservice = \u0027NT AUTHORITY\\SYSTEM\u0027 THEN \u0027[WARNING: Running SQL Server Agent under this account is not supported]\u0027 \r\n", "\t\t\tWHEN @clustered = 1 AND @accntsqlagentservice = \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server Agent under this account is not supported]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @accntsqlagentservice = \u0027NT AUTHORITY\\SYSTEM\u0027 THEN \u0027[WARNING: Running SQL Server Agent under this account is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @accntsqlagentservice = \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[WARNING: Running SQL Server Agent under this account is not recommended]\u0027 \r\n", "\t\t\tWHEN @osver IS NULL THEN \u0027[WARNING: Could not determine Windows version for check]\u0027\r\n", "\t\t-- MSA for WS2008R2 or higher, SQL Server 2012 or higher, non-clustered (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntsqlagentservice <> \u0027NT SERVICE\\SQLSERVERAGENT\u0027 AND @accntsqlagentservice NOT LIKE \u0027NT SERVICE\\SQLAGENT$%\u0027 THEN \u0027[INFORMATION: SQL Server Agent is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server_Analysis_Services\u0027 AS [Service], @statusolapservice AS [Status], @accntolapservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statusolapservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statusolapservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntolapservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntolapservice = @accntsqlservice THEN \u0027[WARNING: Running SQL Server Analysis Services under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver <= 10 AND @accntolapservice <> \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 AND @accntdtsservice <> \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[INFORMATION: SQL Server Analysis Services is not running with the default account]\u0027\r\n", "\t\t\tWHEN @osver IS NULL THEN \u0027[WARNING: Could not determine Windows version for check]\u0027\r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) <= 6.0 AND @accntolapservice <> \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[INFORMATION: SQL Server Analysis Services is not running with the default account]\u0027\r\n", "\t\t-- MSA for WS2008R2 or higher, SQL Server 2005 or higher, non-clustered (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntolapservice <> \u0027NT SERVICE\\MSSQLServerOLAPService\u0027 AND @accntolapservice NOT LIKE \u0027NT SERVICE\\MSOLAP$%\u0027 THEN \u0027[INFORMATION: SQL Server Analysis Services is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server_Integration_Services\u0027 AS [Service], @statusdtsservice AS [Status], @accntdtsservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statusdtsservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statusdtsservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntdtsservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntdtsservice = @accntsqlservice THEN \u0027[WARNING: Running SQL Server Integration Services under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\tWHEN @osver IS NULL THEN \u0027[WARNING: Could not determine Windows version for check]\u0027\r\n", "\t\t\tWHEN CONVERT(DECIMAL(3,1), @osver) <= 6.0 AND @accntdtsservice <> \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 AND @accntdtsservice <> \u0027NT AUTHORITY\\LOCALSYSTEM\u0027 THEN \u0027[INFORMATION: SQL Server Integration Services is not running with the default account]\u0027\r\n", "\t\t-- MSA for WS2008R2 or higher, SQL Server 2012 or higher (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\tWHEN @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntdtsservice NOT IN (\u0027NT SERVICE\\MSDTSSERVER100\u0027, \u0027NT SERVICE\\MSDTSSERVER110\u0027) THEN \u0027[INFORMATION: SQL Server Integration Services is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server_Reporting_Services\u0027 AS [Service], @statusrsservice AS [Status], @accntrsservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statusrsservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statusrsservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntrsservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntrsservice = @accntsqlservice THEN \u0027[WARNING: Running SQL Server Reporting Services under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\tWHEN @clustered = 0 AND @sqlmajorver <= 10 AND @accntrsservice <> \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 AND @accntdtsservice <> \u0027NT AUTHORITY\\LOCALSYSTEM\u0027 THEN \u0027[INFORMATION: SQL Server Reporting Services is not running with the default account]\u0027\r\n", "\t\t\tWHEN @osver IS NULL THEN \u0027[WARNING: Could not determine Windows version for check]\u0027\r\n", "\t\t\tWHEN @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) <= 6.0 AND @accntrsservice <> \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[INFORMATION: SQL Server Reporting Services is not running with the default account]\u0027\r\n", "\t\t-- MSA for WS2008R2 or higher, SQL Server 2012 or higher (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\tWHEN @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntrsservice <> \u0027NT SERVICE\\ReportServer\u0027 AND @accntrsservice NOT LIKE \u0027NT SERVICE\\ReportServer$%\u0027 THEN \u0027[INFORMATION: SQL Server Reporting Services is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027Full-Text\u0027 AS [Service], ISNULL(@statusftservice, \u0027Not Installed\u0027) AS [Status], ISNULL(@accntftservice,\u0027\u0027) AS [Account],\r\n", "\t\t\t\tCASE WHEN (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 1 THEN \r\n", "\t\t\tCASE WHEN @statusftservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\t\tWHEN @statusftservice LIKE \u0027Stopped%\u0027 THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\t\tWHEN @accntftservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\t\tWHEN @accntftservice = @accntsqlservice THEN \u0027[WARNING: Running Full-Text Daemon under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\t\tWHEN @accntftservice = \u0027NT AUTHORITY\\SYSTEM\u0027 THEN \u0027[WARNING: Running Full-Text Service under this account is not recommended]\u0027 \r\n", "\t\t\t\tWHEN @osver IS NULL THEN \u0027[WARNING: Could not determine Windows version for check]\u0027\r\n", "\t\t\t\tWHEN @sqlmajorver <= 10 AND @accntftservice = \u0027NT AUTHORITY\\NETWORKSERVICE\u0027 THEN \u0027[WARNING: Running Full-Text Service under this account is not recommended]\u0027 \r\n", "\t\t\t\tWHEN @sqlmajorver <= 10 AND @accntftservice <> \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[WARNING: Full-Text Daemon is not running with the default account]\u0027\r\n", "\t\t\t\tWHEN @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) <= 6.0 AND @accntftservice <> \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[WARNING: Full-Text Daemon is not running with the default account]\u0027\r\n", "\t\t\t-- MSA for WS2008R2 or higher, SQL Server 2012 or higher (https://docs.microsoft.com/previous-versions/sql/sql-server-2012/ms143504(v=sql.110)#Default_Accts))\r\n", "\t\t\t\tWHEN @sqlmajorver >= 11 AND CONVERT(DECIMAL(3,1), @osver) >= 6.1 AND @accntftservice <> \u0027NT SERVICE\\MSSQLFDLauncher\u0027 AND @accntftservice NOT LIKE \u0027NT SERVICE\\MSSQLFDLauncher$%\u0027 THEN \u0027[WARNING: Full-Text Daemon is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 END \r\n", "\t\tELSE \u0027[INFORMATION: Service is not installed]\u0027 \r\n", "\t\tEND AS [Deviation]\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Service_Status\u0027 AS [Check], \u0027SQL_Server_Browser\u0027 AS [Service], @statusbrowservice AS [Status], @accntbrowservice AS [Account],\r\n", "\t\t\t\tCASE WHEN @statusbrowservice = \u0027Not Installed\u0027 THEN \u0027[INFORMATION: Service is not installed]\u0027\r\n", "\t\t\tWHEN @statusbrowservice LIKE \u0027Stopped%\u0027 AND @instancename IS NOT NULL THEN \u0027[WARNING: Service is stopped on a named instance]\u0027\r\n", "\t\t\tWHEN @statusbrowservice LIKE \u0027Stopped%\u0027 AND @instancename IS NULL THEN \u0027[WARNING: Service is stopped]\u0027\r\n", "\t\t\tWHEN @accntbrowservice IS NULL THEN \u0027[WARNING: Could not detect account for check]\u0027 \r\n", "\t\t\tWHEN @accntbrowservice = @accntsqlservice THEN \u0027[WARNING: Running SQL Server Browser under the same account as SQL Server is not recommended]\u0027 \r\n", "\t\t\tWHEN @accntbrowservice <> \u0027NT AUTHORITY\\LOCALSERVICE\u0027 THEN \u0027[WARNING: SQL Server Browser is not running with the default account]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 \r\n", "\t\tEND AS [Deviation];\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Service Accounts Status\" checks. Otherwise, you must be a granted EXECUTE permissions on xp_regread and xp_servicecontrol. Bypassing check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "c56c784b-f455-4035-9078-b801245e377a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Service Accounts and SPN registration subsection\r\n", "- You can set @spn_check to OFF if you want to skip SPN checks. (Or not run this Block!)\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n" ], "metadata": { "azdata_cell_guid": "80ac3d03-bcfc-4707-9569-ff395801c9e3" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Service Accounts and SPN registration\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @accntsqlservice IS NOT NULL AND @accntsqlservice NOT IN (\u0027NT AUTHORITY\\LOCALSERVICE\u0027,\u0027NT AUTHORITY\\SYSTEM\u0027,\u0027LocalSystem\u0027,\u0027NT AUTHORITY\\NETWORKSERVICE\u0027) AND @allow_xpcmdshell = 1 AND @spn_check = 1\r\n", "BEGIN\r\n", "\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\tFROM sys.credentials\r\n", "\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0)) -- Is not sysadmin but proxy account exists\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0))\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (\u0027 |-Configuration options set for SPN check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tDECLARE /*@CMD NVARCHAR(4000),*/ @line int, @linemax int, @SPN VARCHAR(8000), @SPNMachine VARCHAR(8000)\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_AcctSPNoutput\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_AcctSPNoutput;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_AcctSPNoutput\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t(\r\n", "\t\t\t\tline int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\t\t[Output] VARCHAR (8000)\r\n", "\t\t\t);\r\n", "\t\t\t\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_DupSPNoutput\u0027))\r\n", "\t\t\tDROP TABLE #xp_cmdshell_DupSPNoutput;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_DupSPNoutput\u0027))\r\n", "\t\t\tCREATE TABLE #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t(\r\n", "\t\t\t\tline int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\t\t[Output] VARCHAR (8000)\r\n", "\t\t\t);\r\n", "\t\t\t\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#FinalDupSPN\u0027))\r\n", "\t\t\tDROP TABLE #FinalDupSPN;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#FinalDupSPN\u0027))\r\n", "\t\t\tCREATE TABLE #FinalDupSPN\r\n", "\t\t\t(\r\n", "\t\t\t\t[SPN] VARCHAR (8000),\r\n", "\t\t\t\t[Accounts] VARCHAR (8000)\r\n", "\t\t\t);\r\n", "\t\t\t\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#ScopedDupSPN\u0027))\r\n", "\t\t\tDROP TABLE #ScopedDupSPN;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#ScopedDupSPN\u0027))\r\n", "\t\t\tCREATE TABLE #ScopedDupSPN\r\n", "\t\t\t(\r\n", "\t\t\t\t[SPN] VARCHAR (8000),\r\n", "\t\t\t\t[Accounts] VARCHAR (8000)\r\n", "\t\t\t);\r\n", "\t\t\tSELECT @CMD = N\u0027SETSPN -P -L \u0027 + @accntsqlservice \r\n", "\t\t\tINSERT INTO #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t\t([Output])\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\tSET @CMD = N\u0027SETSPN -P -X\u0027\r\n", "\t\t\tINSERT INTO #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t\t([Output])\r\n", "\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\tSELECT @SPNMachine = \u0027%MSSQLSvc/\u0027 + CONVERT(NVARCHAR(100),SERVERPROPERTY(\u0027MachineName\u0027)) + \u0027%\u0027;\r\n", "\t\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\t\tb.line\r\n", "\t\t\tFROM #xp_cmdshell_AcctSPNoutput a INNER JOIN #xp_cmdshell_DupSPNoutput b ON REPLACE(UPPER(a.[Output]),CHAR(9), \u0027\u0027) = LEFT(REPLACE(UPPER(b.[Output]),CHAR(9), \u0027\u0027), LEN(REPLACE(UPPER(a.[Output]),\u0027 \u0027, \u0027\u0027))))\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tDECLARE curSPN CURSOR FAST_FORWARD FOR SELECT b.line, REPLACE(a.[Output], CHAR(9), \u0027\u0027)\r\n", "\t\t\t\tFROM #xp_cmdshell_AcctSPNoutput a INNER JOIN #xp_cmdshell_DupSPNoutput b ON REPLACE(UPPER(a.[Output]),CHAR(9), \u0027\u0027) = LEFT(REPLACE(UPPER(b.[Output]),CHAR(9), \u0027\u0027), LEN(REPLACE(UPPER(a.[Output]),\u0027 \u0027, \u0027\u0027)))\r\n", "\t\t\t\tWHERE a.[Output] LIKE \u0027%MSSQLSvc%\u0027\r\n", "\t\t\t\tOPEN curSPN\r\n", "\t\t\t\tFETCH NEXT FROM curSPN INTO @line, @SPN\r\n", "\t\t\t\tWHILE @@FETCH_STATUS = 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t\t@linemax = line\r\n", "\t\t\t\t\tFROM #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t\t\tWHERE line > @line AND [Output] IS NULL;\r\n", "\t\t\t\t\tINSERT INTO #FinalDupSPN\r\n", "\t\t\t\t\tSELECT QUOTENAME(@SPN), QUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027))\r\n", "\t\t\t\t\tFROM #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t\t\tWHERE line > @line AND line < @linemax;\r\n", "\t\t\t\t\tIF EXISTS (SELECT [Output]\r\n", "\t\t\t\t\tFROM #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t\t\tWHERE line = @line AND [Output] LIKE @SPNMachine)\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tINSERT INTO #ScopedDupSPN\r\n", "\t\t\t\t\t\tSELECT QUOTENAME(@SPN), QUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027))\r\n", "\t\t\t\t\t\tFROM #xp_cmdshell_DupSPNoutput\r\n", "\t\t\t\t\t\tWHERE line > @line AND line < @linemax;\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tFETCH NEXT FROM curSPN INTO @line, @SPN\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE curSPN\r\n", "\t\t\t\tDEALLOCATE curSPN\r\n", "\t\t\tEND\r\n", "\t\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\t\t[Output]\r\n", "\t\t\tFROM #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\tWHERE [Output] LIKE \u0027%MSSQLSvc%\u0027)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tIF EXISTS (SELECT [Output]\r\n", "\t\t\t\tFROM #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t\tWHERE [Output] LIKE \u0027%MSSQLSvc%\u0027 AND [Output] LIKE @SPNMachine)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027MSSQLSvc_SPNs_SvcAcct_CurrServer\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation], QUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027)) AS SPN\r\n", "\t\t\t\t\tFROM #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t\t\tWHERE [Output] LIKE @SPNMachine\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027MSSQLSvc_SPNs_SvcAcct_CurrServer\u0027 AS [Check], \u0027[WARNING: There is no registered MSSQLSvc SPN for the current service account in the scoped server name, preventing the use of Kerberos authentication]\u0027 AS [Deviation];\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF EXISTS (SELECT [Output]\r\n", "\t\t\t\tFROM #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t\tWHERE [Output] LIKE \u0027%MSSQLSvc%\u0027 AND [Output] NOT LIKE @SPNMachine)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027MSSQLSvc_SPNs_SvcAcct\u0027 AS [Check], \u0027[INFORMATION: There are other MSSQLSvc SPNs registered for the current service account]\u0027 AS [Deviation], QUOTENAME(REPLACE([Output], CHAR(9), \u0027\u0027)) AS SPN\r\n", "\t\t\t\t\tFROM #xp_cmdshell_AcctSPNoutput\r\n", "\t\t\t\t\tWHERE [Output] LIKE \u0027%MSSQLSvc%\u0027 AND [Output] NOT LIKE @SPNMachine\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027MSSQLSvc_SPNs_SvcAcct\u0027 AS [Check], \u0027[WARNING: There is no registered MSSQLSvc SPN for the current service account, preventing the use of Kerberos authentication]\u0027 AS [Deviation];\r\n", "\t\t\tEND\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #ScopedDupSPN) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Dup_MSSQLSvc_SPNs_Acct_CurrServer\u0027 AS [Check], \u0027[WARNING: There are duplicate registered MSSQLSvc SPNs in the domain, for the SPN in the scoped server name]\u0027 AS [Deviation], REPLACE([SPN], CHAR(9), \u0027\u0027), [Accounts] AS [Information]\r\n", "\t\t\t\tFROM #ScopedDupSPN\r\n", "\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Dup_MSSQLSvc_SPNs_Acct_CurrServer\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\t\tEND\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #FinalDupSPN) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Dup_MSSQLSvc_SPNs_Acct\u0027 AS [Check], \u0027[WARNING: There are duplicate registered MSSQLSvc SPNs in the domain]\u0027 AS [Deviation], [SPN], [Accounts]\r\n", "\t\t\t\tFROM #FinalDupSPN\r\n", "\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Service_Account_checks\u0027 AS [Category], \u0027Dup_MSSQLSvc_SPNs_Acct\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\t\tEND\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Service Accounts and SPN registration subsection - Error raised in TRY block 9. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tIF @xcmd = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\t\tIF @sao = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Service Accounts and SPN registration\" check. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: xp_cmdshell. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"Service Accounts and SPN registration\" check was skipped: either spn checks were not allowed, xp_cmdshell was not allowed or the service account is not a domain account.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Instance Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "902066bc-f9f3-4968-9a5d-1b6ab5459fd9", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Recommended build check subsection\r\n" ], "metadata": { "azdata_cell_guid": "fdd35c35-5185-44cd-b278-86c2a28e3150" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "/*\r\n", "RAISERROR (N\u0027 |-Starting Recommended build check\u0027, 10, 1) WITH NOWAIT\r\n", "SELECT \u0027Instance_checks\u0027 AS [Category], \u0027Recommended_Build\u0027 AS [Check],\r\n", "\tCASE WHEN (@sqlmajorver = 9 AND @sqlbuild < 5000)\r\n", "\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 0 AND @sqlbuild < 6000)\r\n", "\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild < 6000)\r\n", "\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild < 7001)\r\n", "\t\t\tOR (@sqlmajorver = 12 AND @sqlbuild < 5000)\r\n", "\t\t\tOR (@sqlmajorver = 13 AND @sqlbuild < 4000)\r\n", "\t\tTHEN \u0027[WARNING: current service pack has been superseded in the current SQL Server version. Install the latest service pack as soon as possible.]\u0027\r\n", "\t\tELSE \u0027[OK]\u0027\r\n", "\tEND AS [Deviation], \r\n", "\tCASE WHEN @sqlmajorver = 9 THEN \u00272005\u0027\r\n", "\t\tWHEN @sqlmajorver = 10 AND @sqlminorver = 0 THEN \u00272008\u0027\r\n", "\t\tWHEN @sqlmajorver = 10 AND @sqlminorver = 50 THEN \u00272008R2\u0027\r\n", "\t\tWHEN @sqlmajorver = 11 THEN \u00272012\u0027\r\n", "\t\tWHEN @sqlmajorver = 12 THEN \u00272014\u0027\r\n", "\t\tWHEN @sqlmajorver = 13 THEN \u00272016\u0027\r\n", "\t\tWHEN @sqlmajorver = 14 THEN \u00272017\u0027\r\n", "\t\tWHEN @sqlmajorver = 15 THEN \u00272019\u0027\r\n", "\tEND AS [Product_Major_Version],\r\n", "\tCONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductLevel\u0027)) AS Product_Level,\r\n", "\tCASE WHEN @sqlmajorver >= 13 OR (@sqlmajorver = 12 AND @sqlbuild >= 2556 AND @sqlbuild < 4100) OR (@sqlmajorver = 12 AND @sqlbuild >= 4427) THEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductBuildType\u0027)) ELSE \u0027NA\u0027 END AS Product_Build_Type,\r\n", "\tCASE WHEN @sqlmajorver >= 13 OR (@sqlmajorver = 12 AND @sqlbuild >= 2556 AND @sqlbuild < 4100) OR (@sqlmajorver = 12 AND @sqlbuild >= 4427) THEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductUpdateLevel\u0027)) ELSE \u0027NA\u0027 END AS Product_Update_Level,\r\n", "\tCASE WHEN @sqlmajorver >= 13 OR (@sqlmajorver = 12 AND @sqlbuild >= 2556 AND @sqlbuild < 4100) OR (@sqlmajorver = 12 AND @sqlbuild >= 4427) THEN CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027ProductUpdateReference\u0027)) ELSE \u0027NA\u0027 END AS Product_Update_Ref_KB;\r\n", "*/\r\n" ], "metadata": { "azdata_cell_guid": "db4f9b64-2082-4e02-82b7-e0efcd1ddb24", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Backup checks subsection\r\n" ], "metadata": { "azdata_cell_guid": "0e16fc99-2e28-42d2-94ac-3e99e3edfb45" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Backup checks\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @nolog int, @nobck int, @nolog24h int, @neverlog int, @neverbck int\r\n", "-- No Full backups\r\n", "\tSELECT @neverbck = COUNT(DISTINCT d.name)\r\n", "\tFROM master.sys.databases d (NOLOCK)\r\n", "\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON d.database_id = tuc.[dbid]\r\n", "\tWHERE database_id NOT IN (2,3)\r\n", "\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\tAND d.name NOT IN (SELECT b.database_name\r\n", "\t\tFROM msdb.dbo.backupset b\r\n", "\t\tWHERE b.type = \u0027D\u0027 AND b.is_copy_only = 0)\r\n", "-- Full backup and no COPY_ONLY backups\r\n", "-- No Full backups in last 7 days\r\n", "\t;WITH\r\n", "\t\tcteFullBcks (cnt)\r\n", "\t\tAS\r\n", "\t\t(\r\n", "\t\t\tSELECT DISTINCT database_name AS cnt\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE b.type = \u0027D\u0027 -- Full backup\r\n", "\t\t\t\tAND b.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL)\r\n", "\t\t-- no snapshots\r\n", "\t\t\tGROUP BY database_name\r\n", "\t\t\tHAVING MAX(backup_finish_date) <= DATEADD(dd, -7, DATEADD(dd, DATEDIFF(dd, 0, GETDATE()) + 1, 0))\r\n", "\t\t)\r\n", "\tSELECT @nobck = COUNT(cnt)\r\n", "\tFROM cteFullBcks;\r\n", "-- Last Log backup precedes last full or diff backup, and DB in Full or Bulk-logged RM\r\n", "\t;WITH\r\n", "\t\tcteLogBcks (cnt)\r\n", "\t\tAS\r\n", "\t\t(\r\n", "\t\t\tSELECT DISTINCT database_name\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE b.type = \u0027L\u0027 -- Log backup\r\n", "\t\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\t\t\tAND recovery_model < 3)\r\n", "\t\t-- not SIMPLE recovery model\r\n", "\t\t\tGROUP BY [database_name]\r\n", "\t\t\tHAVING MAX(backup_finish_date) < (SELECT MAX(backup_finish_date)\r\n", "\t\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\t\tWHERE c.type IN (\u0027D\u0027,\u0027I\u0027) -- Full or Differential backup\r\n", "\t\t\t\tAND c.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\tAND c.database_name = b.database_name)\r\n", "\t\t)\r\n", "\tSELECT @nolog = COUNT(cnt)\r\n", "\tFROM cteLogBcks;\r\n", "-- No Log backup since last full or diff backup, and DB in Full or Bulk-logged RM\r\n", "\tSELECT @neverlog = COUNT(DISTINCT database_name)\r\n", "\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\tWHERE database_name IN (SELECT name\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\tAND recovery_model < 3) -- not SIMPLE recovery model\r\n", "\t\tAND EXISTS (SELECT DISTINCT database_name\r\n", "\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\tWHERE c.type IN (\u0027D\u0027,\u0027I\u0027) -- Full or Differential backup\r\n", "\t\t\tAND c.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\tAND c.database_name = b.database_name) -- Log backup\r\n", "\t\tAND NOT EXISTS (SELECT DISTINCT database_name\r\n", "\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\tWHERE c.type = \u0027L\u0027 -- Log Backup\r\n", "\t\t\tAND c.database_name = b.database_name);\r\n", "-- Log backup since last full or diff backup is older than 24h, and DB in Full ar Bulk-logged RM\r\n", "\t;WITH\r\n", "\t\tcteLogBcks2 (cnt)\r\n", "\t\tAS\r\n", "\t\t(\r\n", "\t\t\tSELECT DISTINCT database_name\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE b.type = \u0027L\u0027 -- Log backup\r\n", "\t\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\t\t\tAND recovery_model < 3)\r\n", "\t\t-- not SIMPLE recovery model\r\n", "\t\t\tGROUP BY database_name\r\n", "\t\t\tHAVING MAX(backup_finish_date) > (SELECT MAX(backup_finish_date)\r\n", "\t\t\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\t\t\tWHERE c.type IN (\u0027D\u0027,\u0027I\u0027) -- Full or Differential backup\r\n", "\t\t\t\t\tAND c.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\t\tAND c.database_name = b.database_name)\r\n", "\t\t\t\tAND MAX(backup_finish_date) <= DATEADD(hh, -24, GETDATE())\r\n", "\t\t)\r\n", "\tSELECT @nolog24h = COUNT(cnt)\r\n", "\tFROM cteLogBcks2;\r\n", "\tIF @nobck > 0 OR @neverbck > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027No_Full_Backups\u0027 AS [Check], \u0027[WARNING: Some databases do not have any Full backups, or the last Full backup is over 7 days]\u0027 AS [Deviation]\r\n", "\t-- No full backups in last 7 days\r\n", "\t\t\t\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027No_Full_Backups\u0027 AS [Information], database_name AS [Database_Name], MAX(backup_finish_date) AS Lst_Full_Backup\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE b.type = \u0027D\u0027 -- Full backup\r\n", "\t\t\t\tAND b.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL)\r\n", "\t\t-- no snapshots\r\n", "\t\t\tGROUP BY database_name\r\n", "\t\t\tHAVING MAX(backup_finish_date) <= DATEADD(dd, -7, DATEADD(dd, DATEDIFF(dd, 0, GETDATE()) + 1, 0))\r\n", "\t\tUNION ALL\r\n", "\t\t-- No full backups in history\r\n", "\t\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027No_Full_Backups\u0027 AS [Information], d.name AS [Database_Name], NULL AS Lst_Full_Backup\r\n", "\t\t\tFROM master.sys.databases d (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON d.database_id = tuc.[dbid]\r\n", "\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\t\tAND recovery_model < 3 -- not SIMPLE recovery model\r\n", "\t\t\t\tAND d.name NOT IN (SELECT b.database_name\r\n", "\t\t\t\tFROM msdb.dbo.backupset b\r\n", "\t\t\t\tWHERE b.type = \u0027D\u0027 AND b.is_copy_only = 0) -- Full backup and no COPY_ONLY backups\r\n", "\t\t\t\tAND d.name NOT IN (SELECT b.database_name\r\n", "\t\t\t\tFROM msdb.dbo.backupset b\r\n", "\t\t\t\tWHERE b.type = \u0027L\u0027)\r\n", "\t-- Log backup\r\n", "\t\tORDER BY [Database_Name]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027No_Full_Backups\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF @nolog > 0 OR @neverlog > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027No_Log_Bcks_since_LstFullorDiff\u0027 AS [Check], \u0027[WARNING: Some databases in Full or Bulk-Logged recovery model do not have any corresponding transaction Log backups since the last Full or Differential backup]\u0027 AS [Deviation]\r\n", "\t\t;WITH\r\n", "\t\t\tBck\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT database_name, MAX(backup_finish_date) AS backup_finish_date\r\n", "\t\t\t\tFROM msdb.dbo.backupset (NOLOCK) b\r\n", "\t\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\t\tWHERE [type] IN (\u0027D\u0027,\u0027I\u0027)\r\n", "\t\t\t-- Full or Differential backup\r\n", "\t\t\t\tGROUP BY database_name\r\n", "\t\t\t)\r\n", "\t-- Log backups since last full or diff is older than 24h\r\n", "\t\t\t\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027No_Log_Bcks_since_LstFullorDiff\u0027 AS [Information], database_name AS [Database_Name], MAX(backup_finish_date) AS Lst_Log_Backup,\r\n", "\t\t\t\t(SELECT backup_finish_date\r\n", "\t\t\t\tFROM Bck c\r\n", "\t\t\t\tWHERE c.database_name = b.database_name) AS Lst_FullDiff_Backup\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE b.type = \u0027L\u0027 -- Log backup\r\n", "\t\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\t\t\tAND recovery_model < 3)\r\n", "\t\t-- not SIMPLE recovery model\r\n", "\t\t\tGROUP BY [database_name]\r\n", "\t\t\tHAVING MAX(backup_finish_date) < (SELECT backup_finish_date\r\n", "\t\t\tFROM Bck c\r\n", "\t\t\tWHERE c.database_name = b.database_name)\r\n", "\t\tUNION ALL\r\n", "\t\t-- No log backup in history but full backup exists\r\n", "\t\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027No_Log_Bcks_since_LstFullorDiff\u0027 AS [Information], database_name AS [Database_Name], NULL AS Lst_Log_Backup, MAX(backup_finish_date) AS Lst_FullDiff_Backup\r\n", "\t\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\t\tWHERE database_name IN (SELECT name\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\t\tAND source_database_id IS NULL -- no snapshots\r\n", "\t\t\t\t\tAND recovery_model < 3) -- not SIMPLE recovery model\r\n", "\t\t\t\tAND EXISTS (SELECT DISTINCT database_name\r\n", "\t\t\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\t\t\tWHERE c.type IN (\u0027D\u0027,\u0027I\u0027) -- Full or Differential backup\r\n", "\t\t\t\t\tAND c.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\t\tAND c.database_name = b.database_name) -- Log backup\r\n", "\t\t\t\tAND NOT EXISTS (SELECT DISTINCT database_name\r\n", "\t\t\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\t\t\tWHERE c.type = \u0027L\u0027 -- Log Backup\r\n", "\t\t\t\t\tAND c.database_name = b.database_name)\r\n", "\t\t\tGROUP BY database_name\r\n", "\t\tORDER BY database_name;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027No_Log_Bcks_since_LstFullorDiff\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF @nolog24h > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Log_Bcks_since_LstFullorDiff_are_older_than_24H\u0027 AS [Check], \u0027[WARNING: Some databases in Full or Bulk-Logged recovery model have their latest log backup older than 24H]\u0027 AS [Deviation]\r\n", "\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027Log_Bcks_since_LstFullorDiff_are_older_than_24H\u0027 AS [Information], database_name AS [Database_Name], MAX(backup_finish_date) AS Lst_Log_Backup\r\n", "\t\tFROM msdb.dbo.backupset b (NOLOCK)\r\n", "\t\t\tINNER JOIN tempdb.dbo.tmpdbs_userchoice tuc ON b.database_name = tuc.[dbname]\r\n", "\t\tWHERE b.type = \u0027L\u0027 -- Log backup\r\n", "\t\t\tAND database_name IN (SELECT name\r\n", "\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\tWHERE database_id NOT IN (2,3)\r\n", "\t\t\t\tAND recovery_model < 3)\r\n", "\t-- not SIMPLE recovery model\r\n", "\t\tGROUP BY database_name\r\n", "\t\tHAVING MAX(backup_finish_date) > (SELECT MAX(backup_finish_date)\r\n", "\t\t\tFROM msdb.dbo.backupset c (NOLOCK)\r\n", "\t\t\tWHERE c.type IN (\u0027D\u0027, \u0027I\u0027) -- Full or Differential backup\r\n", "\t\t\t\tAND c.is_copy_only = 0 -- No COPY_ONLY backups\r\n", "\t\t\t\tAND c.database_name = b.database_name)\r\n", "\t\t\tAND MAX(backup_finish_date) <= DATEADD(hh, -24, GETDATE())\r\n", "\t\tORDER BY [database_name];\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Log_Bcks_since_LstFullorDiff_are_older_than_24H\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "0ef5cc44-579a-4b4d-b4f4-f8969bed65f9", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Global trace flags subsection\r\n" ], "metadata": { "azdata_cell_guid": "ea4fba5d-820c-418a-b126-0a01b71fc69a" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Global trace flags\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @tracestatus TABLE (TraceFlag NVARCHAR(40),\r\n", "\t\t[Status] tinyint,\r\n", "\t\t[Global] tinyint,\r\n", "\t\t[Session] tinyint);\r\n", "\tINSERT INTO @tracestatus\r\n", "\tEXEC (\u0027DBCC TRACESTATUS WITH NO_INFOMSGS\u0027)\r\n", "\tIF @sqlmajorver >= 11\r\n", "BEGIN\r\n", "\t\tDECLARE @dbname0 NVARCHAR(1000), @dbid0 int, @sqlcmd0 NVARCHAR(4000), @has_colstrix int, @min_compat_level tinyint\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblColStoreIXs\u0027))\r\n", "\tDROP TABLE #tblColStoreIXs;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblColStoreIXs\u0027))\r\n", "\tCREATE TABLE #tblColStoreIXs\r\n", "\t\t(\r\n", "\t\t\t[DBName] NVARCHAR(1000),\r\n", "\t\t\t[Schema] VARCHAR(100),\r\n", "\t\t\t[Table] VARCHAR(255),\r\n", "\t\t\t[Object] VARCHAR(255)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname0 = [dbname], @dbid0 = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd0 = \u0027USE \u0027 + QUOTENAME(@dbname0) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname0, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], QUOTENAME(t.name), QUOTENAME(o.[name]), i.name \r\n", "FROM sys.indexes AS i (NOLOCK)\r\n", "INNER JOIN sys.objects AS o (NOLOCK) ON o.[object_id] = i.[object_id]\r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = i.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE i.[type] IN (5,6,7)\u0027\r\n", "\t\t\t-- 5 = Clustered columnstore; 6 = Nonclustered columnstore; 7 = Nonclustered hash\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblColStoreIXs\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd0\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Global trace flags subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid0\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tSELECT @has_colstrix = COUNT(*)\r\n", "\t\tFROM #tblColStoreIXs\r\n", "\t\tSELECT @min_compat_level = min([compatibility_level])\r\n", "\t\tfrom tempdb.dbo.tmpdbs0\r\n", "\tEND;\r\n", "\tIF (SELECT COUNT(TraceFlag)\r\n", "\tFROM @tracestatus\r\n", "\tWHERE [Global]=1) = 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check], \u0027[There are no Global Trace Flags active]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "-- Plan affecting TFs: http://support.microsoft.com/kb/2801413 and https://support.microsoft.com/kb/2964518\r\n", "-- All supported TFs: http://aka.ms/traceflags\r\n", "\tIF EXISTS (SELECT TraceFlag\r\n", "\tFROM @tracestatus\r\n", "\tWHERE [Global] = 1)\r\n", "BEGIN\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 174)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF174 increases the SQL Server Database Engine plan cache bucket count from 40,009 to 160,001 on 64-bit systems]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 174\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 174)\r\n", "\t\t\tAND ((@sqlmajorver = 11 AND @sqlbuild >= 3368)\r\n", "\t\t\tOR (@sqlmajorver = 12 AND @sqlbuild >= 2480)\r\n", "\t\t\tOR (@sqlmajorver >= 13)\t\t\r\n", "\t\t)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF174 to increase the SQL Server plan cache bucket count from 40,009 to 160,001 on 64-bit systems]\u0027\r\n", "\t\t\tAS [Deviation], NULL AS \u0027TraceFlag\u0027\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 174\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 634)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF634 disables the background columnstore compression task]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 634\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 652)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF652 disables read-aheads during scans]\u0027 --http://support.microsoft.com/kb/920093\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 652\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 661)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF661 disables the ghost cleanup background task]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 661\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 834)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 11\r\n", "\t\t\t\t\tAND @has_colstrix > 0\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF834 (Large Page Support for BP) is discouraged when Columnstore Indexes are used. In SQL Server 2019, use TF876 instead (preview) to set large-page allocations for columnstore only]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 834\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 845)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 2 --Standard SKU\r\n", "\t\t\t\t\tAND ((@sqlmajorver = 10 AND ((@sqlminorver = 0 AND @sqlbuild >= 2714) OR @sqlminorver = 50))\r\n", "\t\t\t\t\tOR (@sqlmajorver = 9 AND @sqlbuild >= 4226))\r\n", "\t\t\t\t\tTHEN \u0027[INFORMATION: TF845 supports locking pages in memory in SQL Server Standard Edition]\u0027\r\n", "\t\t\t\tWHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 2 --Standard SKU\r\n", "\t\t\t\t\tAND @sqlmajorver >= 11 \r\n", "\t\t\t\t\tTHEN \u0027[WARNING: TF845 is not needed in SQL 2012 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 845\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 902)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: TF902 Bypasses execution of database upgrade script when installing a Cumulative Update or Service Pack]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 902\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1117)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 --SQL 2016\r\n", "\t\t\tTHEN \u0027[WARNING: TF1117 is not needed in SQL 2016 and higher versions]\u0027\r\n", "\t\t\tELSE \u0027[INFORMATION: TF1117 autogrows all files at the same time and affects all databases]\u0027 \r\n", "\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1117\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1117)\r\n", "\t\t\tAND (@sqlmajorver < 13)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF1117 to autogrow all files at the same time and affects all databases]\u0027\r\n", "\t\t\tAS [Deviation], NULL AS \u0027TraceFlag\u0027;\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1118)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 --SQL 2016\r\n", "\t\t\tTHEN \u0027[WARNING: TF1118 is not needed in SQL 2016 and higher versions]\u0027\r\n", "\t\t\tELSE \u0027[INFORMATION: TF1118 forces uniform extent allocations instead of mixed page allocations]\u0027\r\n", "\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1118\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1118)\r\n", "\t\t\tAND (@sqlmajorver < 13)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF1118 to force uniform extent allocations instead of mixed page allocations]\u0027\r\n", "\t\t\tAS [Deviation], NULL AS \u0027TraceFlag\u0027;\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1204)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF1204 returns the resources and types of locks participating in a deadlock and also the current command affected]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1204\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1211)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: TF1211 disables lock escalation based on memory pressure, or based on number of locks, increasing the amount of locks held]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1211\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1222)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF1222 returns the resources and types of locks participating in a deadlock and also the current command affected]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1222\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1224)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: TF1224 disables lock escalation based on the number of locks, and only escalates locks under memory pressure, increasing the amount of locks held]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1224\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1229)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: TF1229 disables lock partitioning, which is a locking mechanism optimization on 16+ CPU servers]\u0027 --https://docs.microsoft.com/sql/relational-databases/sql-server-transaction-locking-and-row-versioning-guide#lock_partitioning\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1229\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1236)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver = 9 OR @sqlmajorver = 10 OR (@sqlmajorver = 11 AND @sqlbuild < 6020) OR (@sqlmajorver = 12 AND @sqlbuild < 4100)\r\n", "\t\t\t\t\tTHEN \u0027[INFORMATION: TF1236 enables database-level lock partitioning]\u0027\r\n", "\t\t\t\tWHEN (@sqlmajorver = 11 AND @sqlbuild >= 6020) OR (@sqlmajorver = 12 AND @sqlbuild >= 4100) OR @sqlmajorver >= 13\r\n", "\t\t\t\t\tTHEN \u0027[WARNING: TF1236 is not needed in SQL 2012 SP3, SQL Server 2014 SP1 and above]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1236\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1236)\r\n", "\t\t\tAND (@sqlmajorver = 9 OR @sqlmajorver = 10 OR (@sqlmajorver = 11 AND @sqlbuild < 6020) OR (@sqlmajorver = 12 AND @sqlbuild < 4100))\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: Consider enabling TF1236 to allow database lock partitioning]\u0027\r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 1462)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[WARNING: TF1462 disables log stream compression for asynchronous availability groups]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 1462\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2312)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver = 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF2312 enables the default CE model for SQL Server 2014 and higher versions, dependent of the compatibility level of the database]\u0027 \r\n", "\t\t\tWHEN @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF2312 enables the default CE model for SQL Server 2014 and higher versions, dependent of the compatibility level of the database]\u0027 \r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2312\r\n", "\t\tEND;\r\n", "\t\t/*\t\r\n", "\tIF EXISTS (SELECT TraceFlag FROM @tracestatus WHERE [Global] = 1 AND TraceFlag = 2330)\r\n", "\tBEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\tCASE WHEN @sqlmajorver = 9\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF2330 supresses recording of index usage stats, which can lead to a non-yielding condition in SQL Server 2005]\u0027 --http://support.microsoft.com/kb/2003031\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\tFROM @tracestatus \r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2330\r\n", "\tEND;\r\n", "*/\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2335)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 9\r\n", "\t\t\t\t\tAND @maxservermem >= 102400 -- 100GB\r\n", "\t\t\t\t\tAND @maxservermem <> 2147483647\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF2335 assumes a fixed amount of memory is available during query optimization. Recommended when server has more than 100GB of memory]\u0027\r\n", "\t\t\tWHEN @sqlmajorver >= 9\r\n", "\t\t\t\t\tAND @maxservermem < 102400 -- 100GB\r\n", "\t\t\t\t\tAND @maxservermem <> 2147483647\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF2335 should not be set on servers with less than 100GB of memory]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2335\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2335)\r\n", "\t\t\tAND @sqlmajorver >= 9\r\n", "\t\t\tAND @maxservermem >= 102400 -- 100GB\r\n", "\t\t\tAND @maxservermem <> 2147483647\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF2335 to use a fixed amount of memory is available during query optimization. Recommended when server has more than 100GB of memory]\u0027 --http://support.microsoft.com/kb/2413549/en-us\r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2340)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2340 causes SQL Server not to use a sort operation (batch sort) for optimized nested loop joins when generating a plan]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2340\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2371)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500) OR @sqlmajorver BETWEEN 11 AND 12 OR (@sqlmajorver >= 13 AND @min_compat_level < 130)\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF2371 changes the fixed rate of the 20pct threshold for update statistics into a dynamic percentage rate]\u0027\r\n", "\t\t\tWHEN @sqlmajorver >= 13 AND @min_compat_level >= 130\r\n", "\t\t\t--TF2371 has no effect if all databases are at least at compatibility level 130.\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF2371 is not needed in SQL 2016 and above when all databases are at compatibility level 130 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2371\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2371)\r\n", "\t\t\tAND ((@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2500) OR @sqlmajorver < 13)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF2371 to change the 20pct fixed rate threshold for update statistics into a dynamic percentage rate]\u0027 --http://blogs.msdn.com/b/saponsqlserver/archive/2011/09/07/changes-to-automatic-update-statistics-in-sql-server-traceflag-2371.aspx\r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2371)\r\n", "\t\t\tAND (@sqlmajorver >= 13 AND @min_compat_level < 130)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Some databases have a compatibility level < 130. Consider enabling TF2371 to change the 20pct fixed rate threshold for update statistics into a dynamic percentage rate]\u0027 --http://blogs.msdn.com/b/saponsqlserver/archive/2011/09/07/changes-to-automatic-update-statistics-in-sql-server-traceflag-2371.aspx\r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2389)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2389 enables automatically generated quick statistics for ascending keys (histogram amendment)]\u0027 \r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2389\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2528)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2528 disables parallel checking of objects by DBCC CHECKDB, DBCC CHECKFILEGROUP, and DBCC CHECKTABLE]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2528\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2549)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2549 forces the DBCC CHECKDB command to assume each database file is on a unique disk drive, but treating different physical files as one logical file]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2549\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2562)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2562 forces the DBCC CHECKDB command to execute in a single batch regardless of the number of indexes in the database]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2562\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 2566)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF2566 runs the DBCC CHECKDB command without data purity check unless DATA_PURITY option is specified]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 2566\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 3023)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF3023 enables CHECKSUM option as default for BACKUP command]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 3023\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 3042)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF3042 bypasses the default backup compression pre-allocation algorithm to allow the backup file to grow only as needed to reach its final size]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 3042\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 3226)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF3226 prevents SQL Server from recording an entry to Errorlog on every successful backup operation]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 3226\r\n", "\t\tEND;\r\n", "\t\t/*\r\n", "\tIF EXISTS (SELECT TraceFlag FROM @tracestatus WHERE [Global] = 1 AND TraceFlag = 4135)\r\n", "\tBEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\tCASE WHEN (@sqlmajorver = 10 AND @sqlminorver = 0 AND @sqlbuild BETWEEN 1818 AND 1835)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 1702)\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF4199 should be used instead of TF4135 in this SQL build]\u0027\r\n", "\t\t\tELSE \u0027[INFORMATION: TF4135 enables query optimizer changes released in SQL Server Cumulative Updates and Service Packs]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\tFROM @tracestatus \r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4135\r\n", "\tEND;\r\n", "\t*/\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4136)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 9 AND @sqlbuild >= 4294)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 0 AND @sqlbuild >= 2766)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 1720)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 2316)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF4136 disables parameter sniffing unless OPTION(RECOMPILE), WITH RECOMPILE or OPTIMIZE FOR value is used]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 4136\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4137)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 10 AND @sqlminorver = 0 AND @sqlbuild >= 5794)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 0 AND @sqlbuild BETWEEN 4326 AND 4371)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 2806)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 2316)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF4137 causes SQL Server to generate a plan using minimum selectivity when estimating AND predicates for filters to account for partial correlation under CE 70]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 4137\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4138)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 4260)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild BETWEEN 2817 AND 2881)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 2325)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF4138 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]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 4138\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4139)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlbuild >= 5532)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 3431 AND @sqlbuild < 5058)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF4139 enables automatically generated quick statistics (histogram amendment) regardless of key column status]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 4139\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 6498)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 12 AND @sqlbuild >= 4416 AND @sqlbuild < 5000)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 12 AND @sqlbuild BETWEEN 2474 AND 2480)\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF6498 enables more than one large query compilation to gain access to the big gateway when there is sufficient memory available, avoiding compilation waits for concurrent large queries]\u0027\r\n", "\t\t\tWHEN (@sqlmajorver = 12 AND @sqlbuild >= 5000) OR @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF6498 is not needed in SQL 2014 SP2, SQL Server 2016 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 6498\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag IN (6532,6533))\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlbuild = 6020)\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF6532 enable performance improvements of query operations with spatial data types]\u0027\r\n", "\t\t\tWHEN (@sqlmajorver = 12 AND @sqlbuild >= 5000)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 6518)\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF6532 and TF 6533 enable performance improvements of query operations with spatial data types]\u0027\r\n", "\t\t\tWHEN @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF6532 and TF 6533 are not needed in SQL Server 2016 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag IN (6532,6533)\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 6532)\r\n", "\t\t\tAND (@sqlmajorver = 11 AND @sqlbuild = 6020)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF6532 to enable performance improvements of query operations with spatial data types]\u0027 \r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag IN (6532,6533))\r\n", "\t\t\tAND ((@sqlmajorver = 11 AND @sqlbuild >= 6518) OR (@sqlmajorver = 12 AND @sqlbuild >= 5000))\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF6532 and TF6533 to enable performance improvements of query operations with spatial data types]\u0027 \r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 6534)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 12 AND @sqlbuild >= 5000)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 6020)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF6534 enables performance improvement of query operations with spatial data types]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 6534\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 6534)\r\n", "\t\t\tAND ((@sqlmajorver = 12 AND @sqlbuild >= 5000) OR (@sqlmajorver = 11 AND @sqlbuild >= 6020) OR @sqlmajorver >= 13)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF6534 to enable performance improvements of query operations with spatial data types]\u0027 \r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 7412)\r\n", "\t\t\tAND ((@sqlmajorver = 13 AND @sqlbuild >= 4001) OR (@sqlmajorver = 14))\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF7412 to enable the lightweight profiling infrastructure]\u0027 -- https://docs.microsoft.com/sql/relational-databases/performance/query-profiling-infrastructure\r\n", "\t\t\tAS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 8015)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN (@sqlmajorver = 11 AND @sqlbuild >= 3349)\r\n", "\t\t\t\t\tOR @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF8015 disables auto-detection and NUMA setup]\u0027 --https://techcommunity.microsoft.com/t5/SQL-Server-Support/How-It-Works-Soft-NUMA-I-O-Completion-Thread-Lazy-Writer-Workers/ba-p/316044\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 8015\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 8032)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 10\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF8032 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]\u0027 \r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 8032\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 8048)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN ((@sqlmajorver = 12 AND @sqlbuild < 4100)\r\n", "\t\t\t\t\tOR (@sqlmajorver BETWEEN 9 AND 11))\r\n", "\t\t\t\t\tAND (@cpucount/@numa) > 8\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF8048 converts NUMA partitioned memory objects into CPU partitioned]\u0027 --https://techcommunity.microsoft.com/t5/SQL-Server-Support/Running-SQL-Server-on-Machines-with-More-Than-8-CPUs-per-NUMA/ba-p/318513\r\n", "\t\t\tWHEN (@sqlmajorver = 12 AND @sqlbuild >= 4100) OR @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF8048 is not needed in SQL Server 2014 SP2, SQL Server 2016 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 8048\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 8048)\r\n", "\t\t\tAND ((@sqlmajorver = 12 AND @sqlbuild < 4100)\r\n", "\t\t\tOR (@sqlmajorver BETWEEN 9 AND 11))\r\n", "\t\t\tAND (@cpucount/@numa) > 8\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF8048 to convert NUMA partitioned memory objects into CPU partitioned. Look in dm_os_wait_stats and dm_os_spin_stats for wait types (CMEMTHREAD and SOS_SUSPEND_QUEUE). Microsoft CSS usually sees the spins jump into the trillions and the waits become a hot spot]\u0027 --https://techcommunity.microsoft.com/t5/SQL-Server-Support/Running-SQL-Server-on-Machines-with-More-Than-8-CPUs-per-NUMA/ba-p/318513\r\n", "\t\t\tAS [Deviation];\r\n", "\t\t-- If the top consumers are partitioned by Node, then use startup trace flag 8048 to further partition by CPU.\r\n", "\t\t\tIF @sqlmajorver < 11\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Is_TF8048_Applicable\u0027 AS [Check], [type],\r\n", "\t\t\t\t\tSUM(page_size_in_bytes)/8192 AS [pages],\r\n", "\t\t\t\t\tSUM(page_size_in_bytes)/1024 AS pages_in_KB,\r\n", "\t\t\t\t\tCASE WHEN (0x20 = creation_options \u0026 0x20) THEN \u0027Global PMO. Cannot be partitioned by CPU/NUMA Node. TF8048 not applicable.\u0027\r\n", "\t\t\t\t\tWHEN (0x40 = creation_options \u0026 0x40) THEN \u0027Partitioned by CPU. TF8048 not applicable.\u0027\r\n", "\t\t\t\t\tWHEN (0x80 = creation_options \u0026 0x80) THEN \u0027Partitioned by Node. Use TF8048 to further partition by CPU\u0027\r\n", "\t\t\t\t\tELSE \u0027Unknown\u0027 END AS [Comment]\r\n", "\t\t\t\tFROM sys.dm_os_memory_objects\r\n", "\t\t\t\tGROUP BY [type], creation_options\r\n", "\t\t\t\tORDER BY SUM(page_size_in_bytes) DESC;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @sqlcmd = N\u0027SELECT \u0027\u0027Instance_checks\u0027\u0027 AS [Category], \u0027\u0027Is_TF8048_Applicable\u0027\u0027 AS [Check], [type], \r\n", "\tSUM(pages_in_bytes)/8192 AS [pages], \r\n", "\tSUM(pages_in_bytes)/1024 AS pages_in_KB,\r\n", "\tCASE WHEN (0x20 = creation_options \u0026 0x20) THEN \u0027\u0027Global PMO. Cannot be partitioned by CPU/NUMA Node. TF8048 not applicable.\u0027\u0027\r\n", "\t\tWHEN (0x40 = creation_options \u0026 0x40) THEN \u0027\u0027Partitioned by CPU. TF8048 not applicable.\u0027\u0027\r\n", "\t\tWHEN (0x80 = creation_options \u0026 0x80) THEN \u0027\u0027Partitioned by Node. Use TF8048 to further partition by CPU\u0027\u0027\r\n", "\t\tELSE \u0027\u0027Unknown\u0027\u0027 END AS [Comment]\r\n", "FROM sys.dm_os_memory_objects\r\n", "GROUP BY [type], creation_options\r\n", "ORDER BY SUM(pages_in_bytes) DESC;\u0027\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 8744)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 12 THEN\r\n", "\t\t\t\t\u0027[INFORMATION: TF8744 disables pre-fetching for the Nested Loop operator]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 8744\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9024)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN ((@sqlmajorver = 12 AND @sqlbuild < 4100)\r\n", "\t\t\t\t\tOR (@sqlmajorver = 11 AND @sqlbuild >= 3349 AND @sqlbuild < 6020))\r\n", "\t\t\t\t\tAND (@cpucount/@numa) > 8\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF9024 converts a global log pool memory object into NUMA node partitioned memory object]\u0027\r\n", "\t\t\tWHEN (@sqlmajorver = 11 AND @sqlbuild >= 6020) OR (@sqlmajorver = 12 AND @sqlbuild >= 4427) OR @sqlmajorver > 12\r\n", "\t\t\t\tTHEN \u0027[WARNING: TF9024 is not needed in SQL Server 2012 SP3, SQL Server 2014 SP1 and above]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9024\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9347)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 THEN\r\n", "\t\t\t\t\u0027[INFORMATION: TF9347 disables batch mode for sort operator]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9347\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9349)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 THEN\r\n", "\t\t\t\t\u0027[INFORMATION: TF9349 disables batch mode for top N sort operator]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9349\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9389)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 THEN\r\n", "\t\t\t\t\u0027[INFORMATION: TF9389 enables dynamic memory grant for batch mode operators]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9389\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9476)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13 THEN\r\n", "\t\t\t\t\u0027[INFORMATION: TF9476 causes SQL Server to generate a plan using the Simple Containment instead of the default Base Containment under New CE]\u0027\r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9476\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 9481)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 12\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF9481 enables Legacy CE model, irrespective of the compatibility level of the database]\u0027 \r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 9481\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 10204)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver >= 13\r\n", "\t\t\t\tTHEN \u0027[INFORMATION: TF10204 disables merge/recompress during columnstore index reorganization]\u0027 \r\n", "\t\t\tELSE \u0027[WARNING: Verify need to set a Non-default TF with current system build and configuration]\u0027\r\n", "\t\t\tEND AS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 10204\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4199)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: TF4199 enables query optimizer changes released in SQL Server Cumulative Updates and Service Packs]\u0027\r\n", "\t\t\tAS [Deviation], TraceFlag\r\n", "\t\t\tFROM @tracestatus\r\n", "\t\t\tWHERE [Global] = 1 AND TraceFlag = 4199;\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t[name] AS [DBName], sd.compatibility_level, \u0027On\u0027 AS [TF_4199],\r\n", "\t\t\t\t\u0027Enabled\u0027 AS \u0027QO_changes_from_previous_DB_compat_levels\u0027,\r\n", "\t\t\t\t\u0027Enabled\u0027 AS \u0027QO_changes_for_current_version_post_RTM\u0027\r\n", "\t\t\tFROM sys.databases sd\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs0 tdbs ON sd.database_id = tdbs.[dbid];\r\n", "\t\tEND;\r\n", "\t\tIF NOT EXISTS (SELECT TraceFlag\r\n", "\t\tFROM @tracestatus\r\n", "\t\tWHERE [Global] = 1 AND TraceFlag = 4199)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t\u0027[INFORMATION: Consider enabling TF4199 to enable query optimizer changes released in SQL Server Cumulative Updates and Service Packs]\u0027\r\n", "\t\t\tAS [Deviation], NULL AS \u0027TraceFlag\u0027;\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Global_Trace_Flags\u0027 AS [Check],\r\n", "\t\t\t\t[name] AS [DBName], sd.compatibility_level, \u0027Off\u0027 AS [TF_4199],\r\n", "\t\t\t\tCASE WHEN sd.compatibility_level >= 130 THEN \u0027Enabled\u0027 ELSE \u0027Disabled\u0027 END AS \u0027QO_changes_from_previous_DB_compat_levels\u0027,\r\n", "\t\t\t\t\u0027Disabled\u0027 AS \u0027QO_changes_for_current_version_post_RTM\u0027\r\n", "\t\t\tFROM sys.databases sd\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs0 tdbs ON sd.database_id = tdbs.[dbid];\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "cd1d1b44-f04f-4952-a84b-2b47d93495ff", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### System configurations subsection\r\n" ], "metadata": { "azdata_cell_guid": "3c9d34ea-eb7a-42c5-8a36-a58617647acd" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting System configurations\u0027, 10, 1) WITH NOWAIT\r\n", "-- Focus on:\r\n", "-- backup compression default\r\n", "-- clr enabled (only enable if needed)\r\n", "-- lightweight pooling (should be zero)\r\n", "-- max degree of parallelism\r\n", "-- cost threshold for parallelism \r\n", "-- max server memory (MB) (set to an appropriate value)\r\n", "-- priority boost (should be zero)\r\n", "-- remote admin connections (should be enabled in a cluster configuration, to allow remote DAC)\r\n", "-- scan for startup procs (should be disabled unless business requirement, like replication)\r\n", "-- min memory per query (default is 1024KB)\r\n", "-- allow updates (no effect in 2005 or above, but should be off)\r\n", "-- max worker threads (should be zero in 2005 or above)\r\n", "-- affinity mask and affinity I/O mask (must not overlap)\r\n", "\tDECLARE @awe tinyint, @ssp bit, @bckcomp bit, @clr bit, @costparallel smallint, @chain bit, @lpooling bit\r\n", "\tDECLARE @pboost bit, @qtimeout int, @cmdshell bit, @deftrace bit, @remote bit, @autoNUMA bit\r\n", "\tDECLARE @minmemqry int, @allowupd bit, @mwthreads int, @recinterval int, @netsize smallint\r\n", "\tDECLARE @ixmem smallint, @adhocqry bit, @locks int, @qrywait int--, @mwthreads_count int\r\n", "\tDECLARE @affin int, @affinIO int, @affin64 int, @affin64IO int, @block_threshold int, @oleauto int\r\n", "--SELECT @mwthreads_count = max_workers_count FROM sys.dm_os_sys_info;\r\n", "\tSELECT @adhocqry = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027Ad Hoc Distributed Queries\u0027;\r\n", "\tSELECT @affin = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027affinity mask\u0027;\r\n", "\tSELECT @affinIO = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027affinity I/O mask\u0027;\r\n", "\tSELECT @affin64 = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027affinity64 mask\u0027;\r\n", "\tSELECT @affin64IO = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027affinity64 I/O mask\u0027;\r\n", "\tSELECT @allowupd = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027allow updates\u0027;\r\n", "\tSELECT @block_threshold = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027blocked process threshold (s)\u0027;\r\n", "\tSELECT @awe = CONVERT(tinyint, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027awe enabled\u0027;\r\n", "\tSELECT @autoNUMA = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027automatic soft-NUMA disabled\u0027;\r\n", "\tSELECT @bckcomp = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027backup compression default\u0027;\r\n", "\tSELECT @clr = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027clr enabled\u0027;\r\n", "\tSELECT @costparallel = CONVERT(smallint, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027cost threshold for parallelism\u0027;\r\n", "\tSELECT @chain = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027cross db ownership chaining\u0027;\r\n", "\tSELECT @deftrace = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027default trace enabled\u0027;\r\n", "\tSELECT @ixmem = CONVERT(smallint, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027index create memory (KB)\u0027;\r\n", "\tSELECT @locks = CONVERT(int, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027locks\u0027;\r\n", "\tSELECT @minmemqry = CONVERT(int, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027min memory per query (KB)\u0027;\r\n", "\tSELECT @mwthreads = CONVERT(smallint, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027max worker threads\u0027;\r\n", "\tSELECT @netsize = CONVERT(smallint, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027network packet size (B)\u0027;\r\n", "\tSELECT @lpooling = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027lightweight pooling\u0027;\r\n", "\tSELECT @recinterval = CONVERT(int, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027recovery interval (min)\u0027;\r\n", "\tSELECT @remote = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027remote admin connections\u0027;\r\n", "\tSELECT @qrywait = CONVERT(int, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027query wait (s)\u0027;\r\n", "\tSELECT @adhoc = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "\tSELECT @oleauto = CONVERT(int, [value])\r\n", "\tFROM sys.configurations (NOLOCK)\r\n", "\tWHERE name = \u0027Ole Automation Procedures\u0027;\r\n", "\tSELECT @pboost = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027priority boost\u0027;\r\n", "\tSELECT @qtimeout = CONVERT(int, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027remote query timeout (s)\u0027;\r\n", "\tSELECT @ssp = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027scan for startup procs\u0027;\r\n", "\tSELECT @cmdshell = CONVERT(bit, [value])\r\n", "\tFROM sys.configurations\r\n", "\tWHERE [Name] = \u0027xp_cmdshell\u0027;\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Allow updates\u0027 AS [Setting], @allowupd AS [Current Value], CASE WHEN @allowupd = 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Microsoft does not support direct catalog updates]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Ad Hoc Distributed Queries\u0027 AS [Setting], @adhocqry AS [Current Value], CASE WHEN @adhocqry = 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Ad Hoc Distributed Queries are enabled]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Auto Soft NUMA Enabled\u0027 AS [Setting], @autoNUMA AS [Current Value], CASE WHEN @sqlmajorver >= 13 AND @autoNUMA = 1 THEN \u0027[WARNING: Auto Soft NUMA is not enabled]\u0027 WHEN @sqlmajorver < 13 THEN \u0027[NA]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Affinity Mask\u0027 AS [Setting], @affin AS [Current Value], CASE WHEN (@affin \u0026 @affinIO <> 0) OR (@affin \u0026 @affinIO <> 0 AND @affin64 \u0026 @affin64IO <> 0) THEN \u0027[WARNING: Current Affinity Mask and Affinity I/O Mask are overlaping]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027[INFORMATION: Configured values for AffinityMask = \u0027 + CONVERT(VARCHAR(10), @affin) + \u0027; Affinity64Mask = \u0027 + CONVERT(VARCHAR(10), @affin64) + \u0027; AffinityIOMask = \u0027 + CONVERT(VARCHAR(10), @affinIO) + \u0027; Affinity64IOMask = \u0027 + CONVERT(VARCHAR(10), @affin64IO) + \u0027]\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Affinity I/O Mask\u0027 AS [Setting], @affinIO AS [Current Value], CASE WHEN (@affin \u0026 @affinIO <> 0) OR (@affin \u0026 @affinIO <> 0 AND @affin64 \u0026 @affin64IO <> 0) THEN \u0027[WARNING: Current Affinity Mask and Affinity I/O Mask are overlaping]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027[INFORMATION: Configured values for AffinityMask = \u0027 + CONVERT(VARCHAR(10), @affin) + \u0027; Affinity64Mask = \u0027 + CONVERT(VARCHAR(10), @affin64) + \u0027; AffinityIOMask = \u0027 + CONVERT(VARCHAR(10), @affinIO) + \u0027; Affinity64IOMask = \u0027 + CONVERT(VARCHAR(10), @affin64IO) + \u0027]\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027AWE\u0027 AS [Setting], @awe AS [Current Value], CASE WHEN @sqlmajorver < 11 AND @arch = 32 AND @systemmem >= 4000 AND @awe = 0 THEN \u0027[WARNING: Current AWE setting is not optimal for this configuration]\u0027 WHEN @sqlmajorver < 11 AND @arch IS NULL THEN \u0027[WARNING: Could not determine architecture needed for check]\u0027 WHEN @sqlmajorver > 10 THEN \u0027[INFORMATION: AWE is not used from SQL Server 2012 onwards]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Backup Compression\u0027 AS [Setting], @bckcomp AS [Current Value], CASE WHEN @sqlmajorver > 9 AND @bckcomp = 0 THEN \u0027[INFORMATION: Backup compression setting is not the recommended value]\u0027 WHEN @sqlmajorver < 10 THEN \u0027[NA]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Blocked Process Threshold\u0027 AS [Setting], @block_threshold AS [Current Value], CASE WHEN @block_threshold > 0 AND @block_threshold < 5 THEN \u0027[WARNING: Blocked Process Threshold setting is not the recommended value. If not disabled, value should be higher than 4]\u0027 WHEN @block_threshold >= 5 THEN \u0027[INFORMATION: Blocked Process Threshold setting is not the default value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027CLR\u0027 AS [Setting], @clr AS [Current Value], CASE WHEN @clr = 1 THEN \u0027[INFORMATION: CLR user code execution setting is enabled]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Cost threshold for Parallelism\u0027 AS [Setting], @costparallel AS [Current Value], CASE WHEN @costparallel = 5 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Cost threshold for Parallelism setting is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Cross DB ownership Chaining\u0027 AS [Setting], @chain AS [Current Value], CASE WHEN @chain = 1 THEN \u0027[WARNING: Cross DB ownership chaining setting is not the recommended value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Default trace\u0027 AS [Setting], @deftrace AS [Current Value], CASE WHEN @deftrace = 0 THEN \u0027[WARNING: Default trace setting is NOT enabled]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Index create memory (KB)\u0027 AS [Setting], @ixmem AS [Current Value], CASE WHEN @ixmem = 0 THEN \u0027[OK]\u0027 WHEN @ixmem > 0 AND @ixmem < @minmemqry THEN \u0027[WARNING: Index create memory should not be less than Min memory per query]\u0027 ELSE \u0027[WARNING: Index create memory is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Lightweight pooling\u0027 AS [Setting], @lpooling AS [Current Value], CASE WHEN @lpooling = 1 THEN \u0027[WARNING: Lightweight pooling setting is not the recommended value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Locks\u0027 AS [Setting], @locks AS [Current Value], CASE WHEN @locks = 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Locks option is not set with the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Max worker threads\u0027 AS [Setting], @mwthreads AS [Current Value], CASE WHEN @mwthreads = 0 THEN \u0027[OK]\u0027 WHEN @mwthreads > 2048 AND @arch = 64 THEN \u0027[WARNING: Max worker threads is larger than 2048 on a x64 system]\u0027 WHEN @mwthreads > 1024 AND @arch = 32 THEN \u0027[WARNING: Max worker threads is larger than 1024 on a x86 system]\u0027 ELSE \u0027[WARNING: Max worker threads is not the default value]\u0027 END AS [Deviation], CASE WHEN @mwthreads = 0 THEN \u0027[INFORMATION: Configured workers = \u0027 + CONVERT(VARCHAR(10),@mwthreads_count) + \u0027]\u0027 ELSE \u0027\u0027 END AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Min memory per query (KB)\u0027 AS [Setting], @minmemqry AS [Current Value], CASE WHEN @minmemqry = 1024 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Min memory per query (KB) setting is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Network packet size (B)\u0027 AS [Setting], @netsize AS [Current Value], CASE WHEN @netsize = 4096 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Network packet size is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Ole Automation Procedures\u0027 AS [Setting], @oleauto AS [Current Value], CASE WHEN @oleauto = 1 THEN \u0027[WARNING: Ole Automation Procedures setting is not the recommended value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Optimize for ad-hoc workloads\u0027 AS [Setting], @adhoc AS [Current Value], CASE WHEN @sqlmajorver > 9 AND @adhoc = 0 THEN \u0027[INFORMATION: Consider enabling the Optimize for ad hoc workloads setting on heavy OLTP ad-hoc workloads to conserve resources]\u0027 WHEN @sqlmajorver < 10 THEN \u0027[NA]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], CASE WHEN @sqlmajorver > 9 AND @adhoc = 0 THEN \u0027[INFORMATION: Should be ON if SQL Server 2008 or higher and OLTP workload]\u0027 ELSE \u0027\u0027 END AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Priority Boost\u0027 AS [Setting], @pboost AS [Current Value], CASE WHEN @pboost = 1 THEN \u0027[CRITICAL: Priority boost setting is not the recommended value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Query wait (s)\u0027 AS [Setting], @qrywait AS [Current Value], CASE WHEN @qrywait = -1 THEN \u0027[OK]\u0027 ELSE \u0027[CRITICAL: Query wait is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Recovery Interval (min)\u0027 AS [Setting], @recinterval AS [Current Value], CASE WHEN @recinterval = 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Recovery interval is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Remote Admin Connections\u0027 AS [Setting], @remote AS [Current Value], CASE WHEN @remote = 0 AND @clustered = 1 THEN \u0027[WARNING: Consider enabling the DAC listener to access a remote connections on a clustered configuration]\u0027 WHEN @remote = 0 AND @clustered = 0 THEN \u0027[INFORMATION: Consider enabling remote connections access to the DAC listener on a stand-alone configuration, should local resources be exhausted]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Remote query timeout\u0027 AS [Setting], @qtimeout AS [Current Value], CASE WHEN @qtimeout = 600 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Remote query timeout is not the default value]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027Startup Stored Procedures\u0027 AS [Setting], @ssp AS [Current Value], CASE WHEN @ssp = 1 AND (@replication IS NULL OR @replication = 0) THEN \u0027[WARNING: Scanning for startup stored procedures setting is not the recommended value]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations\u0027 AS [Check], \u0027xp_cmdshell\u0027 AS [Setting], @cmdshell AS [Current Value], CASE WHEN @cmdshell = 1 THEN \u0027[WARNING: xp_cmdshell setting is enabled]\u0027 ELSE \u0027[OK]\u0027 END AS [Deviation], \u0027\u0027 AS [Comment];\r\n", "\tIF (SELECT COUNT([name])\r\n", "\tFROM master.sys.configurations\r\n", "\tWHERE [value] <> [value_in_use] AND [is_dynamic] = 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations_Pending\u0027 AS [Check], \u0027[WARNING: There are system configurations with differences between running and configured values]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations_Pending\u0027 AS [Information], [name] AS [Setting],\r\n", "\t\t\t[value] AS \u0027Config_Value\u0027,\r\n", "\t\t\t[value_in_use] AS \u0027Run_Value\u0027\r\n", "\t\tFROM master.sys.configurations (NOLOCK)\r\n", "\t\tWHERE [value] <> [value_in_use] AND [is_dynamic] = 0;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027System_Configurations_Pending\u0027AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "35c04cb4-2dea-4dc6-a52b-940f7fe8517a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### IFI subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n" ], "metadata": { "azdata_cell_guid": "f7cb97c0-e1bd-459c-8115-1fd914cbcd52" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting IFI\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @IFIStatus NVARCHAR(256)\r\n", "\tIF ((@sqlmajorver = 13 AND @sqlbuild < 4000) OR @sqlmajorver < 13)\r\n", "BEGIN\r\n", "\t\tIF @allow_xpcmdshell = 1\r\n", "\tBEGIN\r\n", "\t\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\t\tFROM sys.credentials\r\n", "\t\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0)) -- Is not sysadmin but proxy account exists\r\n", "\t\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\t\tAND (SELECT COUNT([name])\r\n", "\t\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0))\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for IFI check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tDECLARE @xp_cmdshell_output2 TABLE ([Output] VARCHAR (8000));\r\n", "\t\t\t\tSET @CMD = (\u0027whoami /priv\u0027)\r\n", "\t\t\t\tINSERT INTO @xp_cmdshell_output2\r\n", "\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD;\r\n", "\t\t\t\t\r\n", "\t\t\t\tIF EXISTS (SELECT *\r\n", "\t\t\t\tFROM @xp_cmdshell_output2\r\n", "\t\t\t\tWHERE [Output] LIKE \u0027%SeManageVolumePrivilege%\u0027)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Instant_Initialization\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\t\t\t\tSET @ifi = 1;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Instant_Initialization\u0027 AS [Check], \u0027[WARNING: Instant File Initialization is disabled. This can impact data file autogrowth times]\u0027 AS [Deviation];\r\n", "\t\t\t\t\tSET @ifi = 0\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027IFI subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Instant Initialization\" check. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: xp_cmdshell. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t\t--RETURN\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027 |- [INFORMATION: \"Instant Initialization\" check was skipped because xp_cmdshell was not allowed.]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE IF ((@sqlmajorver = 13 AND @sqlbuild >= 4000) OR @sqlmajorver > 13)\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = N\u0027SELECT @IFIStatusOUT = instant_file_initialization_enabled FROM sys.dm_server_services WHERE servicename LIKE \u0027\u0027SQL Server%\u0027\u0027 AND servicename NOT LIKE \u0027\u0027SQL Server Agent%\u0027\u0027\u0027;\r\n", "\t\tSET @params = N\u0027@IFIStatusOUT NVARCHAR(256) OUTPUT\u0027;\r\n", "\t\tEXECUTE sp_executesql @sqlcmd, @params, @IFIStatusOUT=@IFIStatus OUTPUT;\r\n", "\t\tIF @IFIStatus = \u0027Y\u0027\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Instant_Initialization\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation];\r\n", "\t\t\tSET @ifi = 1;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Instant_Initialization\u0027 AS [Check], \u0027[WARNING: Instant File Initialization is disabled. This can impact data file autogrowth times]\u0027 AS [Deviation];\r\n", "\t\t\tSET @ifi = 0\r\n", "\t\tEND\r\n", "\tEND;\r\n", "\tINSERT INTO tempdb.dbo.dbvars (VarName, VarValue) VALUES (\u0027ifi\u0027, @ifi )\r\n" ], "metadata": { "azdata_cell_guid": "3591d6e6-b554-48e8-9fc6-dd25ca68215b", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Full Text Configurations subsection\r\n" ], "metadata": { "azdata_cell_guid": "3af50294-ac29-4f86-9822-44c5b3105505" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Full Text Configurations\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @FullTextDefaultPath NVARCHAR(512), @fterr tinyint\r\n", "\tDECLARE @fttbl TABLE ([KeyExist] int)\r\n", "\tDECLARE @FullTextDetails TABLE (FullText_ResourceUsage tinyint,\r\n", "\t\t[DefaultPath] NVARCHAR(512),\r\n", "\t\t[ConnectTimeout] int,\r\n", "\t\t[DataTimeout] int,\r\n", "\t\t[AllowUnsignedBinaries] bit,\r\n", "\t\t[LoadOSResourcesEnabled] bit,\r\n", "\t\t[CatalogUpgradeOption] tinyint)\r\n", "\tSET @fterr = 0\r\n", "\tIF (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 1\r\n", "BEGIN\r\n", "\t\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1) OR ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) = 1)\r\n", "\tBEGIN\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO @fttbl\r\n", "\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027, N\u0027SOFTWARE\\Microsoft\\MSSQLServer\\Setup\u0027 -- check if Full-Text path exists\r\n", "\t\t\tIF (SELECT [KeyExist]\r\n", "\t\t\tFROM @fttbl) = 1\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027, N\u0027SOFTWARE\\Microsoft\\MSSQLServer\\Setup\u0027, N\u0027FullTextDefaultPath\u0027, @FullTextDefaultPath OUTPUT, NO_OUTPUT;\r\n", "\t\t\tEND\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Full Text Configurations subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Missing permissions for full \"Full Text Configurations\" checks. Bypassing Full Text path check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\t\tINSERT INTO @FullTextDetails\r\n", "\t\tSELECT FULLTEXTSERVICEPROPERTY(\u0027ResourceUsage\u0027), ISNULL(@FullTextDefaultPath, N\u0027\u0027) AS [Default Path],\r\n", "\t\t\tISNULL(FULLTEXTSERVICEPROPERTY(\u0027ConnectTimeout\u0027),0), ISNULL(FULLTEXTSERVICEPROPERTY(\u0027DataTimeout\u0027),0),\r\n", "\t\t\tCASE WHEN @sqlmajorver >= 9 THEN\r\n", "\t\t\tFULLTEXTSERVICEPROPERTY(\u0027VerifySignature\u0027) ELSE NULL \r\n", "\tEND AS [AllowUnsignedBinaries],\r\n", "\t\t\tCASE WHEN @sqlmajorver >= 9 THEN\r\n", "\t\tFULLTEXTSERVICEPROPERTY(\u0027LoadOSResources\u0027) ELSE NULL \r\n", "\tEND AS [LoadOSResourcesEnabled],\r\n", "\t\t\tCASE WHEN @sqlmajorver >= 10 THEN\r\n", "\t\tFULLTEXTSERVICEPROPERTY(\u0027UpgradeOption\u0027) ELSE NULL \r\n", "\tEND AS [CatalogUpgradeOption];\r\n", "\t\tIF @sqlmajorver <= 9 AND (SELECT FullText_ResourceUsage\r\n", "\t\t\tFROM @FullTextDetails) <> 3\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Full_Text\u0027 AS [Check], \u0027[INFORMATION: FullText Resource usage setting is not default]\u0027 AS [Deviation],\r\n", "\t\t\t\tCASE WHEN FullText_ResourceUsage < 3 THEN \u0027[Least Aggressive Usage Level]\u0027\r\n", "\t\t\t\t\tWHEN FullText_ResourceUsage = 4 THEN \u0027[More Aggressive Usage Level]\u0027\r\n", "\t\t\t\t\tWHEN FullText_ResourceUsage = 5 THEN \u0027[Most Aggressive Usage Level]\u0027\r\n", "\t\t\tEND AS [Comment]\r\n", "\t\t\tFROM @FullTextDetails;\r\n", "\t\t\tSET @fterr = @fterr + 1\r\n", "\t\tEND\r\n", "\t\tIF @sqlmajorver >= 9 AND (SELECT [AllowUnsignedBinaries]\r\n", "\t\t\tFROM @FullTextDetails) = 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Full_Text\u0027 AS [Check], \u0027[WARNING: FullText Binaries verification setting is not default]\u0027 AS [Deviation],\r\n", "\t\t\t\t\u0027[Do not verify whether or not binaries are signed]\u0027 AS [Comment];\r\n", "\t\t\tSET @fterr = @fterr + 1\r\n", "\t\tEND\r\n", "\t\tIF @sqlmajorver >= 9 AND (SELECT [LoadOSResourcesEnabled]\r\n", "\t\t\tFROM @FullTextDetails) = 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Full_Text\u0027 AS [Check], \u0027[WARNING: FullText OS Resource utilization setting is not default]\u0027 AS [Deviation],\r\n", "\t\t\t\t\u0027[Load OS filters and word breakers]\u0027 AS [Comment];\r\n", "\t\t\tSET @fterr = @fterr + 1\r\n", "\t\tEND\r\n", "\t\tIF @fterr = 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Full_Text\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation],\r\n", "\t\t\t\t\u0027[All FullText settings are aligned with defaults]\u0027 AS [Comment];\r\n", "\t\tEND\r\n", "\tEND;\r\n", "\tIF (SELECT ISNULL(FULLTEXTSERVICEPROPERTY(\u0027IsFulltextInstalled\u0027),0)) = 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Full_Text\u0027 AS [Check], NULL AS [Deviation], \u0027[FullText search is not installed]\u0027 AS [Comment];\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "914a25fb-0b80-4c95-a719-eb135072aad5", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Deprecated features subsection\r\n" ], "metadata": { "azdata_cell_guid": "a4fb8168-0fa1-46ba-a3ef-02aa0d263c29" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Deprecated or Discontinued features\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(instance_name)\r\n", "\tFROM sys.dm_os_performance_counters\r\n", "\tWHERE [object_name] = \u0027SQLServer:Deprecated Features\u0027 AND cntr_value > 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features\u0027 AS [Check], \u0027[WARNING: Deprecated or Discontinued features are being used. Deprecated features are scheduled to be removed in a future release of SQL Server. Discontinued features have been removed from specific versions of SQL Server]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features\u0027 AS [Information], instance_name, cntr_value AS [Times_used_since_startup]\r\n", "\t\tFROM sys.dm_os_performance_counters (NOLOCK)\r\n", "\t\tWHERE [object_name] LIKE \u0027%Deprecated Features%\u0027 AND cntr_value > 0\r\n", "\t\tORDER BY instance_name;\r\n", "\t\tRAISERROR (N\u0027 |-Deprecated or Discontinued Features are being used - finding usage in SQL modules and SQL Agent jobs\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t/*DECLARE @dbid int, @dbname VARCHAR(1000), @sqlcmd NVARCHAR(4000)*/\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecated\u0027))\r\n", "\tDROP TABLE #tblDeprecated;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecated\u0027))\r\n", "\tCREATE TABLE #tblDeprecated\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[Schema] VARCHAR(100),\r\n", "\t\t\t[Object] VARCHAR(255),\r\n", "\t\t\t[Type] VARCHAR(100),\r\n", "\t\t\tDeprecatedFeature VARCHAR(30),\r\n", "\t\t\tDeprecatedIn tinyint,\r\n", "\t\t\tDiscontinuedIn tinyint\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecatedJobs\u0027))\r\n", "\tDROP TABLE #tblDeprecatedJobs;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecatedJobs\u0027))\r\n", "\tCREATE TABLE #tblDeprecatedJobs\r\n", "\t\t(\r\n", "\t\t\t[JobName] sysname,\r\n", "\t\t\t[Step] VARCHAR(100),\r\n", "\t\t\tDeprecatedFeature VARCHAR(30),\r\n", "\t\t\tDeprecatedIn tinyint,\r\n", "\t\t\tDiscontinuedIn tinyint\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tblKeywords\u0027))\r\n", "\tDROP TABLE ##tblKeywords;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tblKeywords\u0027))\r\n", "\tCREATE TABLE ##tblKeywords\r\n", "\t\t(\r\n", "\t\t\tKeywordID int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\tKeyword VARCHAR(64),\r\n", "\t\t-- the keyword itself\r\n", "\t\t\tDeprecatedIn tinyint,\r\n", "\t\t\tDiscontinuedIn tinyint\r\n", "\t\t);\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.indexes (NOLOCK)\r\n", "\t\tWHERE name = N\u0027UI_Keywords\u0027 AND [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tblKeywords\u0027))\r\n", "\tCREATE UNIQUE INDEX UI_Keywords ON ##tblKeywords(Keyword);\r\n", "\t\tINSERT INTO ##tblKeywords\r\n", "\t\t\t(Keyword, DeprecatedIn, DiscontinuedIn)\r\n", "\t-- discontinued on sql 2005\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT \u0027disk init\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027disk resize\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027for load\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc dbrepair\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc newalloc\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc pintable\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc unpintable\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc rowlock\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc textall\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc textalloc\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027*=\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027=*\u0027, NULL, 9\r\n", "\t\tUNION ALL\r\n", "\t\t-- deprecated on sql 2005 and not yet discontinued\r\n", "\t\t\tSELECT \u0027setuser\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_helpdevice\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addtype\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_attach_db\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_attach_single_file_db\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_bindefault\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_unbindefault\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_bindrule\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_unbindrule\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027create default\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027drop default\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027create rule\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027drop rule\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_renamedb\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_resetstatus\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc dbreindex\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc indexdefrag\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc showcontig\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addextendedproc\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dropextendedproc\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_helpextendedproc\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_loginconfig\u0027, 1, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_fulltext_catalog\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_fulltext_table\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_fulltext_column\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_fulltext_database\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_tables\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_columns\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_catalogs\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_tables_cursor\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_columns_cursor\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_help_fulltext_catalogs_cursor\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_get_sql\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_indexoption\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_lock\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027indexkey_property\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027file_id\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_certify_removable\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_create_removable\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dbremove\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addapprole\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dropapprole\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addlogin\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_droplogin\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_adduser\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dropuser\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_grantdbaccess\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_revokedbaccess\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addrole\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_droprole\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_approlepassword\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_password\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_changeobjectowner\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_defaultdb\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_defaultlanguage\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_denylogin\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_grantlogin\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_revokelogin\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027user_id\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_srvrolepermission\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dbfixedrolepermission\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027text\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027ntext\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027image\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027textptr\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027textvalid\u0027, 9, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t-- discontinued on sql 2008\r\n", "\t\t\tSELECT \u0027sp_addalias\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027no_log\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027truncate_only\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027backup transaction\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dbcc concurrencyviolation\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addgroup\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_changegroup\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dropgroup\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_helpgroup\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_makewebtask\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dropwebtask\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_runwebtask\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_enumcodepages\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027dump\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027load\u0027, 9, 10\r\n", "\t\tUNION ALL\r\n", "\t\t-- undocumented system stored procedures are removed from sql server:\r\n", "\t\t\tSELECT \u0027sp_articlesynctranprocs\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_diskdefault\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_eventlog\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_getmbcscharlen\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_helplog\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_helpsql\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_ismbcsleadbyte\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_lock2\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_msget_current_activity\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_msset_current_activity\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_msobjessearch\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_enum_activescriptengines\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_eventlog\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_getadmingroupname\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_getfiledetails\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_getlocalsystemaccountname\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_isntadmin\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_mslocalsystem\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_msnt2000\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_msplatform\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_setsecurity\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_varbintohexstr\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t-- undocumented system tables are removed from sql server:\r\n", "\t\t\tSELECT \u0027spt_datatype_info\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027spt_datatype_info_ext\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027spt_provider_types\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027spt_server_info\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027spt_values\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysfulltextnotify \u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027syslocks\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysproperties\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysprotects_aux\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysprotects_view\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_catalogs\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_column_privileges\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_columns\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_foreign_keys\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_indexes\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_primary_keys\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_provider_types\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_schemata\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_statistics\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_table_privileges\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_tables\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysremote_views\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027syssegments\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sysxlogins\u0027, NULL, 10\r\n", "\t\tUNION ALL\r\n", "\t\t-- deprecated on sql 2008 and not yet discontinued\r\n", "\t\t\tSELECT \u0027sp_droptype\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027@@remserver\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027remote_proc_transactions\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addumpdevice\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_grantlogin\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027xp_revokelogin\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027grant all\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027deny all\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027revoke all\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_virtualservernodes\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_servershareddrives\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027writetext\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027updatetext\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027readtext\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027torn_page_detection\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027set rowcount\u0027, 10, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t-- discontinued on sql 2012\r\n", "\t\t\tSELECT \u0027dbo_only\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- on restore statements\r\n", "\t\t\tSELECT \u0027mediapassword\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- on backup statements\r\n", "\t\t\tSELECT \u0027password\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- on backup statements except for media\r\n", "\t\t\tSELECT \u0027with append\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- on triggers\r\n", "\t\t\tSELECT \u0027sp_dboption\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027databaseproperty\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fastfirstrow\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_addserver\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- for linked servers\r\n", "\t\t\tSELECT \u0027sp_dropalias\u0027, 9, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027disable_def_cnst_chk\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_activedirectory_obj\u0027, NULL, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_activedirectory_scp\u0027, NULL, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_activedirectory_start\u0027, NULL, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.database_principal_aliases\u0027, NULL, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027compute\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027compute by\u0027, 10, 11\r\n", "\t\tUNION ALL\r\n", "\t\t-- deprecated on sql 2012 and not yet discontinued\r\n", "\t\t\tSELECT \u0027sp_change_users_login\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_depends\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_getbindtoken\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_bindsession\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fmtonly\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027raiserror\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_db_increased_partitions\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027databasepropertyex(\u0027\u0027isfulltextenabled\u0027\u0027)\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_dbcmptlevel\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027set ansi_nulls off\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027set ansi_padding off\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027set concat_null_yields_null off\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027set offsets\u0027, 11, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t-- deprecated on sql 2014 and not yet discontinued\r\n", "\t\t\tSELECT \u0027sys.numbered_procedures\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.numbered_procedure_parameters\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.sql_dependencies\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_db_vardecimal_storage_format\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_estimated_rowsize_reduction_for_vardecimal\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_trace_create\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_trace_setevent\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sp_trace_setstatus\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_trace_geteventinfo\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_trace_getfilterinfo\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027fn_trace_gettable\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.traces\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.trace_events\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.trace_event_bindings\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.trace_categories\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.trace_columns\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027sys.trace_subclass_values\u0027, 12, NULL\r\n", "\t\tUNION ALL\r\n", "\t\t-- discontinued on sql 2019\r\n", "\t\t\tSELECT \u0027disable_interleaved_execution_tvf\u0027, 10, 15\r\n", "\t\tUNION ALL\r\n", "\t\t-- as DB Scoped config\r\n", "\t\t\tSELECT \u0027disable_batch_mode_memory_grant_feedback\u0027, 10, 15\r\n", "\t\tUNION ALL\r\n", "\t\t-- as DB Scoped config\r\n", "\t\t\tSELECT \u0027disable_batch_mode_adaptive_joins\u0027, 10, 15\r\n", "\t-- as DB Scoped config\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT N\u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], ss.name AS [Schema_Name], so.name AS [Object_Name], so.type_desc, tk.Keyword, tk.DeprecatedIn, tk.DiscontinuedIn\r\n", "FROM sys.sql_modules sm (NOLOCK)\r\n", "INNER JOIN sys.objects so (NOLOCK) ON sm.[object_id] = so.[object_id]\r\n", "INNER JOIN sys.schemas ss (NOLOCK) ON so.[schema_id] = ss.[schema_id]\r\n", "CROSS JOIN ##tblKeywords tk (NOLOCK)\r\n", "WHERE PATINDEX(\u0027\u0027%\u0027\u0027 + tk.Keyword + \u0027\u0027%\u0027\u0027, LOWER(sm.[definition]) COLLATE DATABASE_DEFAULT) > 1\r\n", "AND OBJECTPROPERTY(sm.[object_id],\u0027\u0027IsMSShipped\u0027\u0027) = 0;\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblDeprecated\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Deprecated or Discontinued Features usage subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tSET @sqlcmd = \u0027USE [msdb];\r\n", "SELECT sj.[name], sjs.step_name, tk.Keyword, tk.DeprecatedIn, tk.DiscontinuedIn\r\n", "FROM msdb.dbo.sysjobsteps sjs (NOLOCK)\r\n", "INNER JOIN msdb.dbo.sysjobs sj (NOLOCK) ON sjs.job_id = sj.job_id\r\n", "CROSS JOIN ##tblKeywords tk (NOLOCK)\r\n", "WHERE PATINDEX(\u0027\u0027%\u0027\u0027 + tk.Keyword + \u0027\u0027%\u0027\u0027, LOWER(sjs.[command]) COLLATE DATABASE_DEFAULT) > 1\r\n", "AND sjs.[subsystem] IN (\u0027\u0027TSQL\u0027\u0027,\u0027\u0027PowerShell\u0027\u0027);\u0027\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #tblDeprecatedJobs\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Deprecated or Discontinued Features usage subsection - Error raised in jobs TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblDeprecated) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features_usage_in_Objects\u0027 AS [Information], DBName, [Schema], [Object], [Type], DeprecatedFeature,\r\n", "\t\t\t\tCASE [DeprecatedIn] WHEN 9 THEN \u00272005\u0027 WHEN 10 THEN \u00272008/2008R2\u0027 WHEN 11 THEN \u00272012\u0027 WHEN 12 THEN \u00272014\u0027 WHEN 13 THEN \u00272016\u0027 WHEN 14 THEN \u00272017\u0027 ELSE NULL END AS [DeprecatedIn],\r\n", "\t\t\t\tCASE [DiscontinuedIn] WHEN 9 THEN \u00272005\u0027 WHEN 10 THEN \u00272008/2008R2\u0027 WHEN 11 THEN \u00272012\u0027 WHEN 12 THEN \u00272014\u0027 WHEN 13 THEN \u00272016\u0027 WHEN 14 THEN \u00272017\u0027 ELSE NULL END AS [DiscontinuedIn],\r\n", "\t\t\t\tCASE WHEN [DiscontinuedIn] IS NULL THEN \u0027[INFORMATION: Deprecated Features are being used. Plan to review objects found using deprecated features and replace deprecated constructs]\u0027 \r\n", "\t\t\t\tELSE \u0027[WARNING: Discontinued Features are being used. Refactor objects found using discontinued features before migrating to a higher version of SQL Server]\u0027 END AS [Comment]\r\n", "\t\t\tFROM #tblDeprecated (NOLOCK);\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features\u0027 AS [Information], NULL AS [DBName], NULL AS [Schema], NULL AS [Object], NULL AS [Type],\r\n", "\t\t\t\tNULL AS [DeprecatedFeature], NULL AS [DeprecatedIn], NULL AS [DiscontinuedIn],\r\n", "\t\t\t\t\u0027[INFORMATION: Deprecated or Discontinued Features may be in use with ad-hoc code]\u0027 AS Comment\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblDeprecatedJobs) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features_usage_in_SQLAgent_jobs\u0027 AS [Information], JobName, [Step], DeprecatedFeature,\r\n", "\t\t\t\tCASE [DeprecatedIn] WHEN 9 THEN \u00272005\u0027 WHEN 10 THEN \u00272008/2008R2\u0027 WHEN 11 THEN \u00272012\u0027 WHEN 12 THEN \u00272014\u0027 WHEN 13 THEN \u00272016\u0027 WHEN 14 THEN \u00272017\u0027 ELSE NULL END AS [DeprecatedIn],\r\n", "\t\t\t\tCASE [DiscontinuedIn] WHEN 9 THEN \u00272005\u0027 WHEN 10 THEN \u00272008/2008R2\u0027 WHEN 11 THEN \u00272012\u0027 WHEN 12 THEN \u00272014\u0027 WHEN 13 THEN \u00272016\u0027 WHEN 14 THEN \u00272017\u0027 ELSE NULL END AS [DiscontinuedIn],\r\n", "\t\t\t\tCASE WHEN [DiscontinuedIn] IS NULL THEN \u0027[INFORMATION: Deprecated Features are being used in SQL Agent jobs. Plan to review job steps found using deprecated features and replace deprecated constructs]\u0027 \r\n", "\t\t\t\tELSE \u0027[WARNING: Discontinued Features are being used in SQL Agent jobs. Refactor job steps found using discontinued features before migrating to a higher version of SQL Server]\u0027 END AS [Comment]\r\n", "\t\t\tFROM #tblDeprecatedJobs (NOLOCK);\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features\u0027 AS [Information], NULL AS [JobName], NULL AS [Step],\r\n", "\t\t\t\tNULL AS [DeprecatedFeature], NULL AS [DeprecatedIn], NULL AS [DiscontinuedIn],\r\n", "\t\t\t\t\u0027[INFORMATION: No Deprecated or Discontinued Features found in SQL Agent jobs]\u0027 AS Comment\r\n", "\t\tEND;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Deprecated_Discontinued_features\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "2350d56a-90cb-455d-8c9b-7f5e97822efd", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Default data collections subsection\r\n" ], "metadata": { "azdata_cell_guid": "27e12af4-dd75-4c5d-ba92-1296448fab41" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting default data collections\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT TOP 1\r\n", "\t\tid\r\n", "\tFROM sys.traces\r\n", "\tWHERE is_default = 1 AND status = 1)\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Default_Trace\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Default_Trace\u0027 AS [Information], \u0027[WARNING: No default trace was found or is not active]\u0027 AS [Deviation], \u0027[Default trace provides troubleshooting assistance to database administrators by ensuring that they have the log data necessary to diagnose problems the first time they occur]\u0027 AS [Comment]\r\n", "\tEND;\r\n", "\tIF EXISTS (SELECT TOP 1\r\n", "\t\tid\r\n", "\tFROM sys.traces\r\n", "\tWHERE [path] LIKE \u0027%blackbox%.trc\u0027 AND status = 1)\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Blackbox_Trace\u0027 AS [Check], \u0027[WARNING: Blackbox trace is configured and running]\u0027 AS [Deviation], \u0027[This trace is designed to behave similarly to an airplane black box, to help you diagnose intermittent server crashes. It consumes more resources than the default trace and should not be running for extended periods of time]\u0027 AS [Comment]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Blackbox_Trace\u0027 AS [Information], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF EXISTS (SELECT TOP 1\r\n", "\t\tid\r\n", "\tFROM sys.traces\r\n", "\tWHERE (is_default = 1 OR [path] LIKE \u0027%blackbox%.trc\u0027) AND status = 1)\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Default_or_Blackbox_Trace\u0027 AS [Information], [id] As trace_id, [path], max_size, max_files, buffer_count, buffer_size, is_default, event_count, dropped_event_count, start_time, last_event_time\r\n", "\t\tFROM sys.traces\r\n", "\t\tWHERE (is_default = 1 OR [path] LIKE \u0027%blackbox%.trc\u0027) AND status = 1\r\n", "\tEND;\r\n", "\tIF @sqlmajorver > 10\r\n", "BEGIN\r\n", "\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\tname\r\n", "\t\tFROM sys.dm_xe_sessions\r\n", "\t\tWHERE [name] = \u0027system_health\u0027)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027xEvent_Session_SystemHealth\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027xEvent_Session_SystemHealth\u0027 AS [Information], \u0027[WARNING: The system_health xEvent session is not active]\u0027 AS [Deviation], \u0027[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]\u0027 AS [Comment]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\tname\r\n", "\t\tFROM sys.dm_xe_sessions\r\n", "\t\tWHERE [name] = \u0027sp_server_diagnostics session\u0027)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027xEvent_Session_sp_server_diagnostics\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027xEvent_Session_sp_server_diagnostics\u0027 AS [Information], \u0027[WARNING: The sp_server_diagnostics xEvent session is not active]\u0027 AS [Deviation], \u0027[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]\u0027 AS [Comment]\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\tname\r\n", "\t\tFROM sys.dm_xe_sessions\r\n", "\t\tWHERE [name] IN (\u0027system_health\u0027, \u0027sp_server_diagnostics session\u0027))\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027xEvent_Session_SystemHealth_sp_server_diagnostics\u0027 AS [Information], name, pending_buffers, total_regular_buffers, regular_buffer_size, total_large_buffers, large_buffer_size, total_buffer_size, buffer_policy_desc, flag_desc,\r\n", "\t\t\t\tdropped_event_count, dropped_buffer_count, blocked_event_fire_time, create_time, largest_event_dropped_size\r\n", "\t\t\tFROM sys.dm_xe_sessions\r\n", "\t\t\tWHERE [name] IN (\u0027system_health\u0027, \u0027sp_server_diagnostics session\u0027)\r\n", "\t\tEND;\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Database and tempDB Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "56a87843-d7ac-4144-9f59-424e6915d3b8", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### User objects in master DB\r\n" ], "metadata": { "azdata_cell_guid": "570707c7-3ba6-4449-8f69-13b8d8703efe" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting User Objects in master DB\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(name)\r\n", "\tFROM master.sys.all_objects\r\n", "\tWHERE is_ms_shipped = 0 AND [type] IN (\u0027AF\u0027,\u0027FN\u0027,\u0027P\u0027,\u0027IF\u0027,\u0027PC\u0027,\u0027TF\u0027,\u0027TR\u0027,\u0027T\u0027,\u0027V\u0027)) >= 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027User_Objects_in_master\u0027 AS [Check], \u0027[WARNING: User objects are created in the master database]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027User_Objects_in_master\u0027 AS [Information], ss.name AS [Schema_Name], sao.name AS [Object_Name], sao.[type_desc] AS [Object_Type], sao.create_date, sao.modify_date\r\n", "\t\tFROM master.sys.all_objects sao\r\n", "\t\t\tINNER JOIN master.sys.schemas ss ON sao.[schema_id] = ss.[schema_id]\r\n", "\t\tWHERE sao.is_ms_shipped = 0\r\n", "\t\t\tAND sao.[type] IN (\u0027AF\u0027,\u0027FN\u0027,\u0027P\u0027,\u0027IF\u0027,\u0027PC\u0027,\u0027TF\u0027,\u0027TR\u0027,\u0027T\u0027,\u0027V\u0027)\r\n", "\t\tORDER BY sao.name, sao.type_desc;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027User_Objects_in_master\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "07e4124f-ce4b-47d2-8521-caf49c216bd1", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### DBs with collation <> master subsection\r\n" ], "metadata": { "azdata_cell_guid": "6610c8c3-153e-452e-8568-76ba4c8f1e5e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBs with collation <> master\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @master_collate NVARCHAR(128), @dif_collate int\r\n", "\tSELECT @master_collate = collation_name\r\n", "\tFROM master.sys.databases (NOLOCK)\r\n", "\tWHERE database_id = 1;\r\n", "\tSELECT @dif_collate = COUNT(collation_name)\r\n", "\tFROM master.sys.databases (NOLOCK)\r\n", "\tWHERE collation_name <> @master_collate;\r\n", "\tIF @dif_collate >= 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Collations\u0027 AS [Check], \u0027[WARNING: Some user databases collation differ from the master Database_Collation]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Collations\u0027 AS [Information], name AS [Database_Name], collation_name AS [Database_Collation], @master_collate AS [Master_Collation]\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE collation_name <> @master_collate;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Collations\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "3e129b13-fb40-45a8-99d4-09e191ba80ee", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### DBs with skewed compatibility level subsection\r\n" ], "metadata": { "azdata_cell_guid": "22577aeb-5dc6-44bf-a0b7-fb0ad5cda395" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBs with skewed compatibility level\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @dif_compat int\r\n", "\tSELECT @dif_compat = COUNT([compatibility_level])\r\n", "\tFROM master.sys.databases (NOLOCK)\r\n", "\tWHERE [compatibility_level] <> @sqlmajorver * 10;\r\n", "\tIF @dif_compat >= 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Compatibility_Level\u0027 AS [Check], \u0027[WARNING: Some user databases have a non-optimal compatibility level]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Compatibility_Level\u0027 AS [Information], name AS [Database_Name], [compatibility_level] AS [Compatibility_Level]\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE [compatibility_level] <> @sqlmajorver * 10;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Compatibility_Level\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "380c1c35-477e-40e3-942c-842840c3e96d", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### User DBs with non-default options subsection\r\n" ], "metadata": { "azdata_cell_guid": "c4643046-c338-4e09-8c94-89e51c2f383e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting User DBs with non-default options\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @cnt int, @cnt_i int\r\n", "\tDECLARE @is_auto_close_on bit, @is_auto_shrink_on bit, @page_verify_option bit\r\n", "\tDECLARE @is_auto_create_stats_on bit, @is_auto_update_stats_on bit\r\n", "\tDECLARE @is_db_chaining_on bit, @is_auto_create_stats_incremental_on bit--, @is_indirect_checkpoint_on bit\r\n", "\tDECLARE @is_trustworthy_on bit, @is_parameterization_forced bit\r\n", "\tDECLARE @dbopterrtb TABLE (id int,\r\n", "\t\tname sysname,\r\n", "\t\tis_auto_close_on bit,\r\n", "\t\tis_auto_shrink_on bit,\r\n", "\t\tpage_verify_option tinyint,\r\n", "\t\tpage_verify_option_desc NVARCHAR(60),\r\n", "\t\tis_auto_create_stats_on bit,\r\n", "\t\tis_auto_update_stats_on bit,\r\n", "\t\tis_db_chaining_on bit,\r\n", "\t--is_indirect_checkpoint_on bit,\r\n", "\t\tis_auto_create_stats_incremental_on bit NULL,\r\n", "\t\tis_trustworthy_on bit,\r\n", "\t\tis_parameterization_forced bit)\r\n", "\tIF @sqlmajorver < 12\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT ROW_NUMBER() OVER(ORDER BY name), name, is_auto_close_on, \r\n", "\tis_auto_shrink_on, page_verify_option, page_verify_option_desc,\t\r\n", "\tis_auto_create_stats_on, is_auto_update_stats_on, is_db_chaining_on,\r\n", "--0 AS is_indirect_checkpoint_on, \r\n", "\tNULL AS is_auto_create_stats_incremental_on, \r\n", "\tis_trustworthy_on, is_parameterization_forced\r\n", "FROM master.sys.databases (NOLOCK)\r\n", "WHERE database_id > 4 OR name = \u0027\u0027model\u0027\u0027\u0027\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSET @sqlcmd = \u0027SELECT ROW_NUMBER() OVER(ORDER BY name), name, is_auto_close_on, \r\n", "\tis_auto_shrink_on, page_verify_option, page_verify_option_desc,\t\r\n", "\tis_auto_create_stats_on, is_auto_update_stats_on, \r\n", "\tis_db_chaining_on, \r\n", "--CASE WHEN target_recovery_time_in_seconds > 0 THEN 1 ELSE 0 END AS is_indirect_checkpoint_on, \r\n", "\tis_auto_create_stats_incremental_on, \r\n", "\tis_trustworthy_on, is_parameterization_forced\r\n", "FROM master.sys.databases (NOLOCK)\r\n", "WHERE database_id > 4 OR name = \u0027\u0027model\u0027\u0027\u0027\r\n", "\tEND;\r\n", "\tINSERT INTO @dbopterrtb\r\n", "\tEXECUTE sp_executesql @sqlcmd;\r\n", "\tSET @cnt = (SELECT COUNT(id)\r\n", "\tFROM @dbopterrtb)\r\n", "\tSET @cnt_i = 1\r\n", "\tSELECT @is_auto_close_on = 0, @is_auto_shrink_on = 0, @page_verify_option = 0, @is_auto_create_stats_on = 0, @is_auto_update_stats_on = 0, @is_db_chaining_on = 0, @is_trustworthy_on = 0, @is_parameterization_forced = 0, @is_auto_create_stats_incremental_on = 0--, @is_indirect_checkpoint_on = 0\r\n", "\tWHILE @cnt_i <> @cnt\r\n", "BEGIN\r\n", "\t\tSELECT @is_auto_close_on = CASE WHEN is_auto_close_on = 1 AND @is_auto_close_on = 0 THEN 1 ELSE @is_auto_close_on END,\r\n", "\t\t\t@is_auto_shrink_on = CASE WHEN is_auto_shrink_on = 1 AND @is_auto_shrink_on = 0 THEN 1 ELSE @is_auto_shrink_on END,\r\n", "\t\t\t@page_verify_option = CASE WHEN page_verify_option <> 2 AND @page_verify_option = 0 THEN 1 ELSE @page_verify_option END,\r\n", "\t\t\t@is_auto_create_stats_on = CASE WHEN is_auto_create_stats_on = 0 AND @is_auto_create_stats_on = 0 THEN 1 ELSE @is_auto_create_stats_on END,\r\n", "\t\t\t@is_auto_update_stats_on = CASE WHEN is_auto_update_stats_on = 0 AND @is_auto_update_stats_on = 0 THEN 1 ELSE @is_auto_update_stats_on END,\r\n", "\t\t\t@is_db_chaining_on = CASE WHEN is_db_chaining_on = 1 AND @is_db_chaining_on = 0 THEN 1 ELSE @is_db_chaining_on END,\r\n", "\t\t--@is_indirect_checkpoint_on = CASE WHEN is_indirect_checkpoint_on = 1 AND @is_indirect_checkpoint_on = 0 THEN 1 ELSE @is_indirect_checkpoint_on END,\r\n", "\t\t\t@is_auto_create_stats_incremental_on = CASE WHEN is_auto_create_stats_incremental_on = 1 AND @is_auto_create_stats_incremental_on IS NULL THEN 1 ELSE @is_auto_create_stats_incremental_on END,\r\n", "\t\t\t@is_trustworthy_on = CASE WHEN is_trustworthy_on = 1 AND @is_trustworthy_on = 0 THEN 1 ELSE @is_trustworthy_on END,\r\n", "\t\t\t@is_parameterization_forced = CASE WHEN is_parameterization_forced = 1 AND @is_parameterization_forced = 0 THEN 1 ELSE @is_parameterization_forced END\r\n", "\t\tFROM @dbopterrtb\r\n", "\t\tWHERE id = @cnt_i;\r\n", "\t\tSET @cnt_i = @cnt_i + 1\r\n", "\tEND\r\n", "\tIF @is_auto_close_on = 1 OR @is_auto_shrink_on = 1 OR @page_verify_option = 1 OR @is_auto_create_stats_on = 1 OR @is_auto_update_stats_on = 1 OR @is_db_chaining_on = 1 OR @is_auto_create_stats_incremental_on = 0 --OR @is_indirect_checkpoint_on = 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options\u0027 AS [Check], \u0027[WARNING: Some user databases may have Non-optimal_Settings]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options\u0027 AS [Information],\r\n", "\t\t\tname AS [Database_Name],\r\n", "\t\t\tRTRIM(\r\n", "\t\t\tCASE WHEN is_auto_close_on = 1 THEN \u0027Auto_Close;\u0027 ELSE \u0027\u0027 END + \r\n", "\t\t\tCASE WHEN is_auto_shrink_on = 1 THEN \u0027Auto_Shrink;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN page_verify_option <> 2 THEN \u0027Page_Verify;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_auto_create_stats_on = 0 THEN \u0027Auto_Create_Stats;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_auto_update_stats_on = 0 THEN \u0027Auto_Update_Stats;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_db_chaining_on = 1 THEN \u0027DB_Chaining;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t--CASE WHEN is_indirect_checkpoint_on = 1 THEN \u0027Indirect_Checkpoint;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_auto_create_stats_incremental_on = 0 THEN \u0027Incremental_Stats;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_trustworthy_on = 1 THEN \u0027Trustworthy_bit;\u0027 ELSE \u0027\u0027 END +\r\n", "\t\t\tCASE WHEN is_parameterization_forced = 1 THEN \u0027Forced_Parameterization;\u0027 ELSE \u0027\u0027 END\r\n", "\t\t) AS [Non-optimal_Settings],\r\n", "\t\t\tCASE WHEN is_auto_close_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Auto_Close],\r\n", "\t\t\tCASE WHEN is_auto_shrink_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Auto_Shrink],\r\n", "\t\t\tpage_verify_option_desc AS [Page_Verify],\r\n", "\t\t\tCASE WHEN is_auto_create_stats_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Auto_Create_Stats],\r\n", "\t\t\tCASE WHEN is_auto_update_stats_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Auto_Update_Stats],\r\n", "\t\t\tCASE WHEN is_db_chaining_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [DB_Chaining],\r\n", "\t\t--CASE WHEN is_indirect_checkpoint_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Indirect_Checkpoint], -- Meant just as a warning that Indirect_Checkpoint is ON. Should be OFF in OLTP systems. Check for high Background Writer Pages/sec counter.\r\n", "\t\t\tCASE WHEN is_auto_create_stats_incremental_on = 1 THEN \u0027ON\u0027 WHEN is_auto_create_stats_incremental_on = 1 THEN \u0027NA\u0027 ELSE \u0027OFF\u0027 END AS [Incremental_Stats],\r\n", "\t\t\tCASE WHEN is_trustworthy_on = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Trustworthy_bit],\r\n", "\t\t\tCASE WHEN is_parameterization_forced = 1 THEN \u0027ON\u0027 ELSE \u0027OFF\u0027 END AS [Forced_Parameterization]\r\n", "\t\tFROM @dbopterrtb\r\n", "\t\tWHERE is_auto_close_on = 1 OR is_auto_shrink_on = 1 OR page_verify_option <> 2 OR is_db_chaining_on = 1 OR (is_auto_create_stats_on = 0 AND @sqlmajorver >= 12)\r\n", "\t\t\tOR is_auto_update_stats_on = 0 OR is_trustworthy_on = 1 OR is_parameterization_forced = 1 OR is_auto_create_stats_incremental_on = 0--OR is_indirect_checkpoint_on = 1;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM master.sys.databases (NOLOCK)\r\n", "\tWHERE is_auto_update_stats_on = 0 AND is_auto_update_stats_async_on = 1) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options_Disabled_Async_AutoUpdate\u0027 AS [Check], \u0027[WARNING: Some databases have Auto_Update_Statistics_Asynchronously ENABLED while Auto_Update_Statistics is DISABLED. If asynch auto statistics update is intended, also enable Auto_Update_Statistics]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options_Disabled_Async_AutoUpdate\u0027 AS [Check], [name]\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE is_auto_update_stats_on = 0 AND is_auto_update_stats_async_on = 1\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Database_Options_Disabled_Async_AutoUpdate\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "1b6d1213-fef5-4184-8cb6-a6aeeafb200c", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Query Store info subsection\r\n" ], "metadata": { "azdata_cell_guid": "38fc370a-997d-4896-b555-9e5ad82d7cee" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 12\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Query Store info\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblQStoreInfo\u0027))\r\n", "\tDROP TABLE #tblQStoreInfo;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblQStoreInfo\u0027))\r\n", "\tCREATE TABLE #tblQStoreInfo\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\tActual_State NVARCHAR(60),\r\n", "\t\t\tFlush_Interval_Sec bigint,\r\n", "\t\t\tInterval_Length_Min bigint,\r\n", "\t\t\tQuery_CaptureMode NVARCHAR(60),\r\n", "\t\t\tMax_Storage_Size_MB bigint,\r\n", "\t\t\tCurrent_Storage_Size_MB bigint\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE is_query_store_on = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], actual_state_desc, flush_interval_seconds, interval_length_minutes, query_capture_mode_desc, max_storage_size_mb, current_storage_size_mb \r\n", "FROM sys.database_query_store_options;\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblQStoreInfo\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Query Store subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tIF (SELECT COUNT([DBName])\r\n", "\t\tFROM #tblQStoreInfo) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Query_Store\u0027 AS [Information], DBName AS [Database_Name],\r\n", "\t\t\t\tActual_State, Flush_Interval_Sec, Interval_Length_Min, Query_CaptureMode, Max_Storage_Size_MB, Current_Storage_Size_MB\r\n", "\t\t\tFROM #tblQStoreInfo\r\n", "\t\t\tORDER BY DBName;\r\n", "\t\tEND\r\n", "END\r\n", "ELSE\r\n", "\tBEGIN\r\n", "\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Query_Store\u0027 AS [Information] , \u0027[INFORMATION: No databases have Query Store enabled]\u0027 AS [Comment];\r\n", "\tEND\r\n" ], "metadata": { "azdata_cell_guid": "277ed927-f170-43fb-81a3-d04b5e5256ef", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Automatic Tuning info subsection\r\n" ], "metadata": { "azdata_cell_guid": "8bf8c637-4b56-4582-95e5-dbeeaa5505f1" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Automatic Tuning info\u0027, 10, 1) WITH NOWAIT\r\n", "IF @sqlmajorver > 13\r\n", "BEGIN\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblAutoTuningInfo\u0027))\r\n", "\tDROP TABLE #tblAutoTuningInfo;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblAutoTuningInfo\u0027))\r\n", "\tCREATE TABLE #tblAutoTuningInfo\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\tAutoTuning_Option NVARCHAR(128),\r\n", "\t\t\tDesired_State NVARCHAR(60),\r\n", "\t\t\tActual_State NVARCHAR(60),\r\n", "\t\t\tDesired_diff_Actual_reason NVARCHAR(60)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027; SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], name, desired_state_desc, actual_state_desc, reason_desc FROM sys.database_automatic_tuning_options;\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblAutoTuningInfo\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\t\t\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Automatic Tuning subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0 \r\n", "\t\t\tSET isdone = 1 \r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\t\tSELECT COUNT(AutoTuning_Option)\r\n", "\t\tFROM #tblAutoTuningInfo\r\n", "\tIF (SELECT COUNT(AutoTuning_Option)\r\n", "\t\tFROM #tblAutoTuningInfo) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\tSELECT \u0027Information\u0027 AS [Category], \u0027Automatic_Tuning\u0027 AS [Information], DBName AS [Database_Name],\r\n", "\t\t\t\tAutoTuning_Option, Desired_State, Actual_State, Desired_diff_Actual_reason\r\n", "\t\t\tFROM #tblAutoTuningInfo\r\n", "\t\t\tORDER BY DBName;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN \r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Automatic_Tuning\u0027 AS [Information] , \u0027[INFORMATION: No databases have Automatic Tuning enabled]\u0027 AS [Comment];\r\n", "\tEND\r\n", "END;\r\n", "ELSE\r\n", "BEGIN \r\n", "\tSELECT \u0027Information\u0027 AS [Category], \u0027Automatic_Tuning\u0027 AS [Information] , \u0027[INFORMATION: No databases have Automatic Tuning enabled]\u0027 AS [Comment];\r\n", "END\r\n" ], "metadata": { "azdata_cell_guid": "7a6e8d9c-1031-4135-801a-56f2bcd03b37", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### DBs with Sparse files subsection\r\n" ], "metadata": { "azdata_cell_guid": "fbc9338c-bd12-48df-bfd0-ab27cfcced05" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBs with Sparse files\u0027, 10, 1) WITH NOWAIT\r\n", "-- https://techcommunity.microsoft.com/t5/SQL-Server-Support/Did-your-backup-program-utility-leave-your-SQL-Server-running-in/ba-p/315840\r\n", "\tIF (SELECT COUNT(sd.database_id)\r\n", "\tFROM sys.databases sd INNER JOIN sys.master_files smf ON sd.database_id = smf.database_id\r\n", "\tWHERE sd.source_database_id IS NULL AND smf.is_sparse = 1) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027DB_nonSnap_Sparse\u0027 AS [Check], \u0027[WARNING: Sparse files were detected that do not belong to a Database Snapshot. You might also notice unexplained performance degradation when query data from these files]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027DB_nonSnap_Sparse\u0027 AS [Information], DB_NAME(sd.database_id) AS database_name, smf.name, smf.physical_name\r\n", "\t\tFROM sys.databases sd\r\n", "\t\t\tINNER JOIN sys.master_files smf ON sd.database_id = smf.database_id\r\n", "\t\tWHERE sd.source_database_id IS NULL AND smf.is_sparse = 1\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027DB_nonSnap_Sparse\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "ff06f656-a67f-4a9c-8808-b698750e8b62", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### DBs Autogrow in percentage subsection\r\n" ], "metadata": { "azdata_cell_guid": "53487379-0345-4468-8ab4-ee9a7472a29a" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBs Autogrow in percentage\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(is_percent_growth)\r\n", "\tFROM sys.master_files\r\n", "\tWHERE is_percent_growth = 1) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Percent_Autogrows\u0027 AS [Check], \u0027[WARNING: 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]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Percent_Autogrows\u0027 AS [Information], database_id,\r\n", "\t\t\tDB_NAME(database_id) AS [Database_Name],\r\n", "\t\t\tmf.name AS [Logical_Name],\r\n", "\t\t\tmf.size*8 AS [Current_Size_KB],\r\n", "\t\t\tmf.type_desc AS [File_Type],\r\n", "\t\t\tmf.[state_desc] AS [File_State],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN \u0027pct\u0027 ELSE \u0027pages\u0027 END AS [Growth_Type],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN mf.growth ELSE mf.growth*8 END AS [Growth_Amount_KB],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 AND mf.growth > 0 THEN ((mf.size*8)*CONVERT(bigint, mf.growth))/100 \r\n", "\t\t\tWHEN is_percent_growth = 0 AND mf.growth > 0 THEN mf.growth*8 \r\n", "\t\t\tELSE 0 END AS [Next_Growth_KB],\r\n", "\t\t\tCASE WHEN @ifi = 0 AND mf.type = 0 THEN \u0027Instant File Initialization is disabled\u0027\r\n", "\t\t\tWHEN @ifi = 1 AND mf.type = 0 THEN \u0027Instant File Initialization is enabled\u0027\r\n", "\t\t\tELSE \u0027\u0027 END AS [Comments],\r\n", "\t\t\tmf.is_read_only\r\n", "\t\tFROM sys.master_files mf (NOLOCK)\r\n", "\t\tWHERE is_percent_growth = 1\r\n", "\t\tGROUP BY database_id, mf.name, mf.size, is_percent_growth, mf.growth, mf.type_desc, mf.[type], mf.[state_desc], mf.is_read_only\r\n", "\t\tORDER BY DB_NAME(mf.database_id), mf.name\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Percent_Autogrows\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "1ac63f19-c033-468e-b594-60ef9a25656e", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### DBs Autogrowth > 1GB in Logs or Data (when IFI is disabled) subsection\r\n" ], "metadata": { "azdata_cell_guid": "a29a0e8d-78e4-4110-ab12-8011236ced2c" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBs Autogrowth > 1GB in Logs or Data (when IFI is disabled)\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(growth)\r\n", "\tFROM sys.master_files (NOLOCK)\r\n", "\tWHERE [type] >= CASE WHEN @ifi = 1 THEN 1 ELSE 0 END\r\n", "\t\tAND [type] < 2\r\n", "\t\tAND ((is_percent_growth = 1 AND ((CONVERT(bigint,size)*8)*growth)/100 > 1048576)\r\n", "\t\tOR (is_percent_growth = 0 AND growth*8 > 1048576))) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Large_Autogrows\u0027 AS [Check], \u0027[WARNING: Some database files have set growth over 1GB. This could lead to extended growth times, slowing down your system]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Large_Autogrows\u0027 AS [Information], database_id,\r\n", "\t\t\tDB_NAME(database_id) AS [Database_Name],\r\n", "\t\t\tmf.name AS [Logical_Name],\r\n", "\t\t\tmf.size*8 AS [Current_Size_KB],\r\n", "\t\t\tmf.[type_desc] AS [File_Type],\r\n", "\t\t\tmf.[state_desc] AS [File_State],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN \u0027pct\u0027 ELSE \u0027pages\u0027 END AS [Growth_Type],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN mf.growth ELSE mf.growth*8 END AS [Growth_Amount],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 AND mf.growth > 0 THEN ((CONVERT(bigint,mf.size)*8)*mf.growth)/100 \r\n", "\t\t\tWHEN is_percent_growth = 0 AND mf.growth > 0 THEN mf.growth*8 \r\n", "\t\t\tELSE 0 END AS [Next_Growth_KB],\r\n", "\t\t\tCASE WHEN @ifi = 0 AND mf.type = 0 THEN \u0027Instant File Initialization is disabled\u0027\r\n", "\t\t\tWHEN @ifi = 1 AND mf.type = 0 THEN \u0027Instant File Initialization is enabled\u0027\r\n", "\t\t\tELSE \u0027\u0027 END AS [Comments],\r\n", "\t\t\tmf.is_read_only\r\n", "\t\tFROM sys.master_files mf (NOLOCK)\r\n", "\t\tWHERE mf.[type] >= CASE WHEN @ifi = 1 THEN 1 ELSE 0 END\r\n", "\t\t\tAND mf.[type] < 2\r\n", "\t\t\tAND ((is_percent_growth = 1 AND ((CONVERT(bigint,mf.size)*8)*mf.growth)/100 > 1048576)\r\n", "\t\t\tOR (is_percent_growth = 0 AND mf.growth*8 > 1048576))\r\n", "\t\tGROUP BY database_id, mf.name, mf.size, is_percent_growth, mf.growth, mf.[type_desc], mf.[type], mf.[state_desc], mf.is_read_only\r\n", "\t\tORDER BY DB_NAME(mf.database_id), mf.name\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Large_Autogrows\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "a7beb995-578a-4d25-af35-287f0042566f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### VLF subsection\r\n" ], "metadata": { "azdata_cell_guid": "f0b3114e-13a5-40db-96a7-dbeb1aa83ff0" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting VLF\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1\r\n", "BEGIN\r\n", "\t\tDECLARE /*@dbid int,*/ /*, @dbname VARCHAR(1000)*/ @count int, @count_used int, @logsize DECIMAL(20,1), @usedlogsize DECIMAL(20,1), @avgvlfsize DECIMAL(20,1)\r\n", "\t\tDECLARE @potsize DECIMAL(20,1), @n_iter int, @n_iter_final int, @initgrow DECIMAL(20,1), @n_init_iter int\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info1\u0027))\r\n", "\tDROP TABLE #log_info1;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info1\u0027))\r\n", "\tCREATE TABLE #log_info1\r\n", "\t\t(\r\n", "\t\t\tdbname NVARCHAR(100),\r\n", "\t\t\tCurrent_log_size_MB DECIMAL(20,1),\r\n", "\t\t\tUsed_Log_size_MB DECIMAL(20,1),\r\n", "\t\t\tPotential_log_size_MB DECIMAL(20,1),\r\n", "\t\t\tCurrent_VLFs int,\r\n", "\t\t\tUsed_VLFs int,\r\n", "\t\t\tAvg_VLF_size_KB DECIMAL(20,1),\r\n", "\t\t\tPotential_VLFs int,\r\n", "\t\t\tGrowth_iterations int,\r\n", "\t\t\tLog_Initial_size_MB DECIMAL(20,1),\r\n", "\t\t\tFile_autogrow_MB DECIMAL(20,1)\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info2\u0027))\r\n", "\tDROP TABLE #log_info2;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info2\u0027))\r\n", "\tCREATE TABLE #log_info2\r\n", "\t\t(\r\n", "\t\t\tdbname NVARCHAR(100),\r\n", "\t\t\tCurrent_VLFs int,\r\n", "\t\t\tVLF_size_KB DECIMAL(20,1),\r\n", "\t\t\tgrowth_iteration int\r\n", "\t\t)\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tIF (SELECT CHARINDEX(CHAR(39), @dbname)) > 0\r\n", "\t\t\t\t\tOR (SELECT CHARINDEX(CHAR(45), @dbname)) > 0\r\n", "\t\t\t\t\tOR (SELECT CHARINDEX(CHAR(47), @dbname)) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Skipping Database ID \u0027 + CONVERT(NVARCHAR, DB_ID(QUOTENAME(@dbname))) + \u0027 due to potential of SQL Injection\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT;\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info3\u0027))\r\n", "\t\t\t\tDROP TABLE #log_info3;\r\n", "\t\t\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info3\u0027))\r\n", "\t\t\t\tCREATE TABLE #log_info3\r\n", "\t\t\t\t\t(\r\n", "\t\t\t\t\t\trecoveryunitid int NULL,\r\n", "\t\t\t\t\t\tfileid tinyint,\r\n", "\t\t\t\t\t\tfile_size bigint,\r\n", "\t\t\t\t\t\tstart_offset bigint,\r\n", "\t\t\t\t\t\tFSeqNo int,\r\n", "\t\t\t\t\t\t[status] tinyint,\r\n", "\t\t\t\t\t\tparity tinyint,\r\n", "\t\t\t\t\t\tcreate_lsn numeric(25,0)\r\n", "\t\t\t\t\t)\r\n", "\t\t\t\t\tSET @query = N\u0027DBCC LOGINFO (N\u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + N\u0027\u0027\u0027) WITH NO_INFOMSGS\u0027\r\n", "\t\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tINSERT INTO #log_info3\r\n", "\t\t\t\t\t\t\t(fileid, file_size, start_offset, FSeqNo, [status], parity, create_lsn)\r\n", "\t\t\t\t\t\tEXEC (@query)\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tINSERT INTO #log_info3\r\n", "\t\t\t\t\t\t\t(recoveryunitid, fileid, file_size, start_offset, FSeqNo, [status], parity, create_lsn)\r\n", "\t\t\t\t\t\tEXEC (@query)\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tSET @count = @@ROWCOUNT\r\n", "\t\t\t\t\tSET @count_used = (SELECT COUNT(fileid)\r\n", "\t\t\t\t\tFROM #log_info3 l\r\n", "\t\t\t\t\tWHERE l.[status] = 2)\r\n", "\t\t\t\t\tSET @logsize = (SELECT (MIN(l.start_offset) + SUM(l.file_size))/1048576.00\r\n", "\t\t\t\t\tFROM #log_info3 l)\r\n", "\t\t\t\t\tSET @usedlogsize = (SELECT (MIN(l.start_offset) + SUM(CASE WHEN l.status <> 0 THEN l.file_size ELSE 0 END))/1048576.00\r\n", "\t\t\t\t\tFROM #log_info3 l)\r\n", "\t\t\t\t\tSET @avgvlfsize = (SELECT AVG(l.file_size)/1024.00\r\n", "\t\t\t\t\tFROM #log_info3 l)\r\n", "\t\t\t\t\tINSERT INTO #log_info2\r\n", "\t\t\t\t\tSELECT @dbname, COUNT(create_lsn), MIN(l.file_size)/1024.00,\r\n", "\t\t\t\t\t\tROW_NUMBER() OVER(ORDER BY l.create_lsn)\r\n", "\t\t\t\t\tFROM #log_info3 l\r\n", "\t\t\t\t\tGROUP BY l.create_lsn\r\n", "\t\t\t\t\tORDER BY l.create_lsn\r\n", "\t\t\t\t\tDROP TABLE #log_info3;\r\n", "\t\t\t\t-- Grow logs in MB instead of GB because of known issue prior to SQL 2012.\r\n", "\t\t\t\t-- More detail here: http://www.sqlskills.com/BLOGS/PAUL/post/Bug-log-file-growth-broken-for-multiples-of-4GB.aspx\r\n", "\t\t\t\t-- and http://connect.microsoft.com/SQLServer/feedback/details/481594/log-growth-not-working-properly-with-specific-growth-sizes-vlfs-also-not-created-appropriately\r\n", "\t\t\t\t-- or https://connect.microsoft.com/SQLServer/feedback/details/357502/transaction-log-file-size-will-not-grow-exactly-4gb-when-filegrowth-4gb\r\n", "\t\t\t\t\tIF @sqlmajorver >= 11\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_iter = (SELECT CASE WHEN @logsize <= 64 THEN 1\r\n", "\t\t\t\t\t\tWHEN @logsize > 64 AND @logsize < 256 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/256, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 256 AND @logsize < 1024 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/512, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 1024 AND @logsize < 4096 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/1024, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 4096 AND @logsize < 8192 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/2048, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 8192 AND @logsize < 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/4096, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/8192, 0)\r\n", "\t\t\t\t\t\tEND)\r\n", "\t\t\t\t\t\tSET @potsize = (SELECT CASE WHEN @logsize <= 64 THEN 1*64\r\n", "\t\t\t\t\t\tWHEN @logsize > 64 AND @logsize < 256 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/256, 0)*256\r\n", "\t\t\t\t\t\tWHEN @logsize >= 256 AND @logsize < 1024 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/512, 0)*512\r\n", "\t\t\t\t\t\tWHEN @logsize >= 1024 AND @logsize < 4096 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/1024, 0)*1024\r\n", "\t\t\t\t\t\tWHEN @logsize >= 4096 AND @logsize < 8192 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/2048, 0)*2048\r\n", "\t\t\t\t\t\tWHEN @logsize >= 8192 AND @logsize < 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/4096, 0)*4096\r\n", "\t\t\t\t\t\tWHEN @logsize >= 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/8192, 0)*8192\r\n", "\t\t\t\t\t\tEND)\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_iter = (SELECT CASE WHEN @logsize <= 64 THEN 1\r\n", "\t\t\t\t\t\tWHEN @logsize > 64 AND @logsize < 256 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/256, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 256 AND @logsize < 1024 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/512, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 1024 AND @logsize < 4096 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/1024, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 4096 AND @logsize < 8192 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/2048, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 8192 AND @logsize < 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/4000, 0)\r\n", "\t\t\t\t\t\tWHEN @logsize >= 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/8000, 0)\r\n", "\t\t\t\t\t\tEND)\r\n", "\t\t\t\t\t\tSET @potsize = (SELECT CASE WHEN @logsize <= 64 THEN 1*64\r\n", "\t\t\t\t\t\tWHEN @logsize > 64 AND @logsize < 256 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/256, 0)*256\r\n", "\t\t\t\t\t\tWHEN @logsize >= 256 AND @logsize < 1024 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/512, 0)*512\r\n", "\t\t\t\t\t\tWHEN @logsize >= 1024 AND @logsize < 4096 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/1024, 0)*1024\r\n", "\t\t\t\t\t\tWHEN @logsize >= 4096 AND @logsize < 8192 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/2048, 0)*2048\r\n", "\t\t\t\t\t\tWHEN @logsize >= 8192 AND @logsize < 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/4000, 0)*4000\r\n", "\t\t\t\t\t\tWHEN @logsize >= 16384 THEN ROUND(CONVERT(FLOAT, ROUND(@logsize, -2))/8000, 0)*8000\r\n", "\t\t\t\t\t\tEND)\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t-- If the proposed log size is smaller than current log, and also smaller than 4GB,\r\n", "\t\t\t\t-- and there is less than 512MB of diff between the current size and proposed size, add 1 grow.\r\n", "\t\t\t\t\tSET @n_iter_final = @n_iter\r\n", "\t\t\t\t\tIF @logsize > @potsize AND @potsize <= 4096 AND ABS(@logsize - @potsize) < 512\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_iter_final = @n_iter + 1\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t-- If the proposed log size is larger than current log, and also larger than 50GB, \r\n", "\t\t\t-- and there is less than 1GB of diff between the current size and proposed size, take 1 grow.\r\n", "\t\t\t\tELSE IF @logsize < @potsize AND @potsize <= 51200 AND ABS(@logsize - @potsize) > 1024\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_iter_final = @n_iter - 1\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @potsize = 0 \r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @potsize = 64\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @n_iter = 0 \r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_iter = 1\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tSET @potsize = (SELECT CASE WHEN @n_iter < @n_iter_final THEN @potsize + (@potsize/@n_iter) \r\n", "\t\t\t\t\t\tWHEN @n_iter > @n_iter_final THEN @potsize - (@potsize/@n_iter) \r\n", "\t\t\t\t\t\tELSE @potsize END)\r\n", "\t\t\t\t\tSET @n_init_iter = @n_iter_final\r\n", "\t\t\t\t\tIF @potsize >= 8192\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @initgrow = @potsize/@n_iter_final\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @potsize >= 64 AND @potsize <= 512\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_init_iter = 1\r\n", "\t\t\t\t\t\tSET @initgrow = 512\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @potsize > 512 AND @potsize <= 1024\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_init_iter = 1\r\n", "\t\t\t\t\t\tSET @initgrow = 1023\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @potsize > 1024 AND @potsize < 8192\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @n_init_iter = 1\r\n", "\t\t\t\t\t\tSET @initgrow = @potsize\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tINSERT INTO #log_info1\r\n", "\t\t\t\t\tVALUES(@dbname, @logsize, @usedlogsize, @potsize, @count, @count_used, @avgvlfsize,\r\n", "\t\t\t\t\t\t\tCASE WHEN @potsize <= 64 THEN (@potsize/(@potsize/@n_init_iter))*4\r\n", "\t\t\t\t\t\tWHEN @potsize > 64 AND @potsize < 1024 THEN (@potsize/(@potsize/@n_init_iter))*8\r\n", "\t\t\t\t\t\tWHEN @potsize >= 1024 THEN (@potsize/(@potsize/@n_init_iter))*16\r\n", "\t\t\t\t\t\tEND,\r\n", "\t\t\t\t\t\t\t@n_init_iter, @initgrow,\r\n", "\t\t\t\t\t\t\tCASE WHEN (@potsize/@n_iter_final) <= 1024 THEN (@potsize/@n_iter_final) ELSE 1024 END\r\n", "\t\t\t\t\t);\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(dbname)\r\n", "\t\tFROM #log_info1\r\n", "\t\tWHERE Current_VLFs >= 50) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files\u0027 AS [Check], \u0027[WARNING: Some user databases have many VLFs. Please review these]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files\u0027 AS [Information], dbname AS [Database_Name], Current_log_size_MB, Used_Log_size_MB,\r\n", "\t\t\t\tPotential_log_size_MB, Current_VLFs, Used_VLFs, Potential_VLFs, Growth_iterations, Log_Initial_size_MB, File_autogrow_MB\r\n", "\t\t\tFROM #log_info1\r\n", "\t\t\tWHERE Current_VLFs >= 50\r\n", "\t\t-- My rule of thumb is 50 VLFs. Your mileage may vary.\r\n", "\t\t\tORDER BY dbname;\r\n", "\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files_per_growth\u0027 AS [Information], #log_info2.dbname AS [Database_Name], #log_info2.Current_VLFs AS VLFs_remain_per_spawn, VLF_size_KB, growth_iteration\r\n", "\t\t\tFROM #log_info2\r\n", "\t\t\t\tINNER JOIN #log_info1 ON #log_info2.dbname = #log_info1.dbname\r\n", "\t\t\tWHERE #log_info1.Current_VLFs >= 50\r\n", "\t\t-- My rule of thumb is 50 VLFs. Your mileage may vary.\r\n", "\t\t\tORDER BY #log_info2.dbname, growth_iteration\r\n", "\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files_agg_per_size\u0027 AS [Information], #log_info2.dbname AS [Database_Name], SUM(#log_info2.Current_VLFs) AS VLFs_per_size, VLF_size_KB\r\n", "\t\t\tFROM #log_info2\r\n", "\t\t\t\tINNER JOIN #log_info1 ON #log_info2.dbname = #log_info1.dbname\r\n", "\t\t\tWHERE #log_info1.Current_VLFs >= 50\r\n", "\t\t-- My rule of thumb is 50 VLFs. Your mileage may vary.\r\n", "\t\t\tGROUP BY #log_info2.dbname, VLF_size_KB\r\n", "\t\t\tORDER BY #log_info2.dbname, VLF_size_KB DESC\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t/*\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files\u0027 AS [Information], dbname AS [Database_Name], Current_log_size_MB, Used_Log_size_MB, Current_VLFs, Used_VLFs\r\n", "\t\tFROM #log_info1\r\n", "\t\tORDER BY dbname;\r\n", "\t\t\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files_per_growth\u0027 AS [Information], dbname AS [Database_Name], Current_VLFs AS VLFs_remain_per_spawn, VLF_size_KB, growth_iteration\r\n", "\t\tFROM #log_info2\r\n", "\t\tORDER BY dbname, growth_iteration\r\n", "\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Virtual_Log_Files_agg_per_size\u0027 AS [Information], dbname AS [Database_Name], SUM(Current_VLFs) AS VLFs_per_size, VLF_size_KB\r\n", "\t\tFROM #log_info2\r\n", "\t\tGROUP BY dbname, VLF_size_KB\r\n", "\t\tORDER BY dbname, VLF_size_KB DESC\r\n", "\t\t*/\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"VLF\" check. Bypassing check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "e5b5120a-c603-4447-aa84-62d26d75a34e", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Data files and Logs / tempDB and user Databases / Backups and Database files in same volume (Mountpoint aware) subsection\r\n", "- You can set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "- If not, default location for .ps1 files is the Log folder.\r\n" ], "metadata": { "azdata_cell_guid": "cf50dac1-066c-413f-a5ff-a880bc468984" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Data files and Logs / tempDB and user Databases / Backups and Database files in same volume (Mountpoint aware)\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @allow_xpcmdshell = 1\r\n", "BEGIN\r\n", "\t\tDECLARE /*@dbid int,*/ @ctr2 int, @ctr3 int, @ctr4 int, @pserr bit\r\n", "\t\tSET @pserr = 0\r\n", "\t\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND (SELECT COUNT(credential_id)\r\n", "\t\t\tFROM sys.credentials\r\n", "\t\t\tWHERE name = \u0027##xp_cmdshell_proxy_account##\u0027) > 0) -- Is not sysadmin but proxy account exists\r\n", "\t\t\tAND (SELECT COUNT(l.name)\r\n", "\t\t\tFROM sys.server_permissions p (NOLOCK) INNER JOIN sys.server_principals l (NOLOCK)\r\n", "\t\t\t\tON p.grantee_principal_id = l.principal_id\r\n", "\t\t\t\t\tAND p.class = 100 -- Server\r\n", "\t\t\t\t\tAND p.state IN (\u0027G\u0027, \u0027W\u0027) -- Granted or Granted with Grant\r\n", "\t\t\t\t\tAND l.is_disabled = 0\r\n", "\t\t\t\t\tAND p.permission_name = \u0027ALTER SETTINGS\u0027\r\n", "\t\t\t\t\tAND QUOTENAME(l.name) = QUOTENAME(USER_NAME())) = 0) -- Is not sysadmin but has alter settings permission \r\n", "\t\t\tOR ((ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) <> 1\r\n", "\t\t\tAND ((SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_fileexist\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_instance_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regread\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OAGetErrorInfo\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OACreate\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027sp_OADestroy\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027) > 0 AND\r\n", "\t\t\t(SELECT COUNT([name])\r\n", "\t\t\tFROM tempdb.dbo.permstbl\r\n", "\t\t\tWHERE [name] = \u0027xp_regenumvalues\u0027) > 0)))\r\n", "\tBEGIN\r\n", "\t\t\tIF @sqlmajorver < 11 OR (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild <= 2500)\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @pstbl TABLE ([KeyExist] int)\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO @pstbl\r\n", "\t\t\t\tEXEC master.sys.xp_regread N\u0027HKEY_LOCAL_MACHINE\u0027, N\u0027SOFTWARE\\Microsoft\\PowerShell\\1\u0027 -- check if Powershell is installed\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Data files and Logs in same volume (Mountpoint aware) subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tSELECT @sao = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027show advanced options\u0027\r\n", "\t\t\t\tSELECT @xcmd = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027xp_cmdshell\u0027\r\n", "\t\t\t\tSELECT @ole = CAST([value] AS smallint)\r\n", "\t\t\t\tFROM sys.configurations (NOLOCK)\r\n", "\t\t\t\tWHERE [name] = \u0027Ole Automation Procedures\u0027\r\n", "\t\t\t\tRAISERROR (\u0027 |-Configuration options set for Data and Log location check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 1;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF (SELECT [KeyExist]\r\n", "\t\t\t\tFROM @pstbl) = 1\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tDECLARE @ctr int\r\n", "\t\t\t\t\tDECLARE @output_hw_tot TABLE ([PS_OUTPUT] NVARCHAR(2048));\r\n", "\t\t\t\t\tDECLARE @output_hw_format TABLE ([volid] smallint IDENTITY(1,1),\r\n", "\t\t\t\t\t\t[HD_Volume] NVARCHAR(2048) NULL)\r\n", "\t\t\t\t\tIF @custompath IS NULL\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tIF @sqlmajorver < 11\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC master..xp_instance_regread N\u0027HKEY_LOCAL_MACHINE\u0027,N\u0027Software\\Microsoft\\MSSQLServer\\Setup\u0027,N\u0027SQLPath\u0027, @path OUTPUT\r\n", "\t\t\t\t\t\t\tSET @path = @path + \u0027\\LOG\u0027\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tSET @sqlcmd = N\u0027SELECT @pathOUT = LEFT([path], LEN([path])-1) FROM sys.dm_os_server_diagnostics_log_configurations\u0027;\r\n", "\t\t\t\t\t\t\tSET @params = N\u0027@pathOUT NVARCHAR(2048) OUTPUT\u0027;\r\n", "\t\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @pathOUT=@path OUTPUT;\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FSO OUT\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FSO, \u0027FolderExists\u0027, @existout OUT, @path\r\n", "\t\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FSO, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling FolderExists Method 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tELSE\r\n", "\t\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\tIF @existout <> 1\r\n", "\t\t\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\t\tSET @path = CONVERT(NVARCHAR(500), SERVERPROPERTY(\u0027ErrorLogFileName\u0027))\r\n", "\t\t\t\t\t\t\t\t\tSET @path = LEFT(@path,LEN(@path)-CHARINDEX(\u0027\\\u0027, REVERSE(@path)))\r\n", "\t\t\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FSO\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @path = CASE WHEN @custompath LIKE \u0027%\\\u0027 THEN LEFT(@custompath, LEN(@custompath)-1) ELSE @custompath END\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tSET @FileName = @path + \u0027\\checkbp_\u0027 + RTRIM(@server) + \u0027.ps1\u0027\r\n", "\t\t\t\t\tEXEC master.dbo.xp_fileexist @FileName, @existout out\r\n", "\t\t\t\t\tIF @existout = 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t-- Scan for local disks\r\n", "\t\t\t\t\t\tSET @Text1 = \u0027[string] $serverName = \u0027\u0027localhost\u0027\u0027\r\n", "$vols = Get-WmiObject -computername $serverName -query \"select Name from Win32_Volume where Capacity <> NULL and DriveType = 3\"\r\n", "foreach($vol in $vols)\r\n", "{\r\n", "\t[string] $drive = \"{0}\" -f $vol.name\r\n", "\tWrite-Output $drive\r\n", "}\u0027\r\n", "\t\t\t\t\t-- Create COM object with FSO\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OACreate \u0027Scripting.FileSystemObject\u0027, @FS OUT\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Creating COM Component 0x%x, %s, %s\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t--Open file\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FS, \u0027OpenTextFile\u0027, @FileID OUT, @FileName, 2, 1\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling OpenTextFile Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not create file \u0027 + @FileName\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\tELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Created file \u0027 + @FileName\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t--Write Text1\r\n", "\t\t\t\t\t\tEXEC @OLEResult = master.dbo.sp_OAMethod @FileID, \u0027WriteLine\u0027, NULL, @Text1\r\n", "\t\t\t\t\t\tIF @OLEResult <> 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tEXEC sp_OAGetErrorInfo @FS, @src OUT, @desc OUT\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Error Calling WriteLine Method 0x%x, %s, %s\u0027 + CHAR(10) + \u0027Could not write to file \u0027 + @FileName\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1, @OLEResult, @src, @desc);\r\n", "\t\t\t\t\t\tEND\r\n", "\t\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FileID\r\n", "\t\t\t\t\t\tEXEC @OLEResult = sp_OADestroy @FS\r\n", "\t\t\t\t\tEND;\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Reusing file \u0027 + @FileName\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tIF @psver = 1\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @CMD = \u0027powershell -NoLogo -NoProfile -File \"\u0027 + @FileName + \u0027\" -ExecutionPolicy RemoteSigned\u0027\r\n", "\t\t\t\t\tEND;\r\n", "\t\t\t\t\tINSERT INTO @output_hw_tot\r\n", "\t\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD\r\n", "\t\t\t\t\tSET @CMD = \u0027del /Q \"\u0027 + @FileName + \u0027\"\u0027\r\n", "\t\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD, NO_OUTPUT\r\n", "\t\t\t\t\tIF (SELECT COUNT([PS_OUTPUT])\r\n", "\t\t\t\t\tFROM @output_hw_tot\r\n", "\t\t\t\t\tWHERE [PS_OUTPUT] LIKE \u0027%cannot be loaded because%\u0027\r\n", "\t\t\t\t\t\tOR [PS_OUTPUT] LIKE \u0027%scripts is disabled%\u0027\r\n", "\t\t\t\t\t\tOR [PS_OUTPUT] LIKE \u0027%scripts est désactivée%\u0027) = 0\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tINSERT INTO @output_hw_format\r\n", "\t\t\t\t\t\t\t([HD_Volume])\r\n", "\t\t\t\t\t\tSELECT RTRIM([PS_OUTPUT])\r\n", "\t\t\t\t\t\tFROM @output_hw_tot\r\n", "\t\t\t\t\t\tWHERE [PS_OUTPUT] IS NOT NULL\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\tELSE\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @pserr = 1\r\n", "\t\t\t\t\t\tRAISERROR (\u0027[WARNING: Powershell script cannot be loaded because the execution of scripts is disabled on this system.\r\n", "To change the execution policy, type the following command in Powershell console: Set-ExecutionPolicy RemoteSigned\r\n", "The Set-ExecutionPolicy cmdlet enables you to determine which Windows PowerShell scripts (if any) will be allowed to run on your computer. \r\n", "Windows PowerShell has four different execution policies:\r\n", "\tRestricted - No scripts can be run. Windows PowerShell can be used only in interactive mode.\r\n", "\tAllSigned - Only scripts signed by a trusted publisher can be run.\r\n", "\tRemoteSigned - Downloaded scripts must be signed by a trusted publisher before they can be run.\r\n", "\t\t|- REQUIRED by BP Check\r\n", "\tUnrestricted - No restrictions; all Windows PowerShell scripts can be run.]\r\n", "\u0027,16,1);\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tSET @CMD2 = \u0027del \u0027 + @FileName\r\n", "\t\t\t\t\tEXEC master.dbo.xp_cmdshell @CMD2, NO_OUTPUT;\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @pserr = 1\r\n", "\t\t\t\t\tRAISERROR (\u0027[WARNING: Powershell is not present. Bypassing Data files and Logs in same volume check]\u0027,16,1);\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @xcmd = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027xp_cmdshell\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @ole = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027Ole Automation Procedures\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tIF @sao = 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tEXEC sp_configure \u0027show advanced options\u0027, 0;\r\n", "\t\t\t\t\tRECONFIGURE WITH OVERRIDE;\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tINSERT INTO @output_hw_format\r\n", "\t\t\t\t\t([HD_Volume])\r\n", "\t\t\t\tEXEC (\u0027SELECT DISTINCT(volume_mount_point) FROM sys.master_files mf CROSS APPLY sys.dm_os_volume_stats (database_id, [file_id]) WHERE mf.[file_id] < 65537\u0027)\r\n", "\t\t\tEND;\r\n", "\t\t\tIF @pserr = 0\r\n", "\t\tBEGIN\r\n", "\t\t\t-- select mountpoints only\r\n", "\t\t\t\tDECLARE @intertbl TABLE (physical_name nvarchar(260))\r\n", "\t\t\t\tINSERT INTO @intertbl\r\n", "\t\t\t\tSELECT physical_name\r\n", "\t\t\t\tFROM sys.master_files t1 (NOLOCK)\r\n", "\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\tWHERE ([database_id] > 4 OR [database_id] = 2)\r\n", "\t\t\t\t\tAND [database_id] <> 32767 AND LEN(t2.HD_Volume) > 3\r\n", "\t\t\t-- select database files in mountpoints\t\t\r\n", "\t\t\t\tDECLARE @filetbl TABLE (database_id int,\r\n", "\t\t\t\t\ttype tinyint,\r\n", "\t\t\t\t\tfile_id int,\r\n", "\t\t\t\t\tphysical_name nvarchar(260),\r\n", "\t\t\t\t\tvolid smallint)\r\n", "\t\t\t\tINSERT INTO @filetbl\r\n", "\t\t\t\t\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK)\r\n", "\t\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE ([database_id] > 4 OR [database_id] = 2) AND [database_id] <> 32767 AND LEN(t2.HD_Volume) > 3\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t-- select database files not in mountpoints\r\n", "\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK)\r\n", "\t\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE ([database_id] > 4 OR [database_id] = 2) AND [database_id] <> 32767 AND physical_name NOT IN (SELECT physical_name\r\n", "\t\t\t\t\t\tFROM @intertbl)\r\n", "\t\t\t\tSELECT @ctr = COUNT(DISTINCT(t1.[database_id]))\r\n", "\t\t\t\tFROM @filetbl t1\r\n", "\t\t\t\t\tINNER JOIN @filetbl t2 ON t1.database_id = t2.database_id\r\n", "\t\t\t\t\t\tAND t1.[type] <> t2.[type]\r\n", "\t\t\t\t\t\tAND ((t1.[type] = 1 AND t2.[type] <> 1) OR (t2.[type] = 1 AND t1.[type] <> 1))\r\n", "\t\t\t\t\t\tAND t1.volid = t2.volid;\r\n", "\t\t\t\tIF @ctr > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Data_and_Log_locations\u0027 AS [Check], \u0027[WARNING: Some user databases have Data and Log files in the same physical volume]\u0027 AS [Deviation]\r\n", "\t\t\t\t\tSELECT DISTINCT \u0027Database_checks\u0027 AS [Category], \u0027Data_and_Log_locations\u0027 AS [Information], DB_NAME(mf.[database_id]) AS [Database_Name], type_desc AS [Type], mf.physical_name\r\n", "\t\t\t\t\tFROM sys.master_files mf (NOLOCK) INNER JOIN @filetbl t1 ON mf.database_id = t1.database_id AND mf.physical_name = t1.physical_name\r\n", "\t\t\t\t\t\tINNER JOIN @filetbl t2 ON t1.database_id = t2.database_id\r\n", "\t\t\t\t\t\t\tAND t1.[type] <> t2.[type]\r\n", "\t\t\t\t\t\t\tAND ((t1.[type] = 1 AND t2.[type] <> 1) OR (t2.[type] = 1 AND t1.[type] <> 1))\r\n", "\t\t\t\t\t\t\tAND t1.volid = t2.volid\r\n", "\t\t\t\t\tORDER BY mf.physical_name\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Data_and_Log_locations\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND;\r\n", "\t\t\t-- select backup mountpoints only\r\n", "\t\t\t\tDECLARE @interbcktbl TABLE (physical_device_name nvarchar(260))\r\n", "\t\t\t\tINSERT INTO @interbcktbl\r\n", "\t\t\t\tSELECT physical_device_name\r\n", "\t\t\t\tFROM msdb.dbo.backupmediafamily t1 (NOLOCK)\r\n", "\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_device_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\tWHERE LEN(t2.HD_Volume) > 3\r\n", "\t\t\t-- select backups in mountpoints only\r\n", "\t\t\t\tDECLARE @bcktbl TABLE (physical_device_name nvarchar(260),\r\n", "\t\t\t\t\tHD_Volume nvarchar(260))\r\n", "\t\t\t\tINSERT INTO @bcktbl\r\n", "\t\t\t\t\t\t\t\t\tSELECT physical_device_name, RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tFROM msdb.dbo.backupmediafamily t1 (NOLOCK)\r\n", "\t\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_device_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE LEN(t2.HD_Volume) > 3\r\n", "\t\t\t\t-- select backups not in mountpoints\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT physical_device_name, RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tFROM msdb.dbo.backupmediafamily t1 (NOLOCK)\r\n", "\t\t\t\t\t\tINNER JOIN @output_hw_format t2 ON LEFT(physical_device_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE physical_device_name NOT IN (SELECT physical_device_name\r\n", "\t\t\t\t\tFROM @interbcktbl);\r\n", "\t\t\t\tSELECT @ctr4 = COUNT(DISTINCT(physical_device_name))\r\n", "\t\t\t\tFROM @bcktbl;\r\n", "\t\t\t\tIF @ctr4 > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Backup_and_Database_locations\u0027 AS [Check], \u0027[WARNING: Some backups and database files are in the same physical volume]\u0027 AS [Deviation]\r\n", "\t\t\t\t\tSELECT DISTINCT \u0027Database_checks\u0027 AS [Category], \u0027Backup_and_Database_locations\u0027 AS [Information], physical_device_name AS [Backup_Location], HD_Volume AS [Volume_with_DB_Files]\r\n", "\t\t\t\t\tFROM @bcktbl\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Backup_and_Database_locations\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND;\r\n", "\t\t\t-- select tempDB mountpoints only\r\n", "\t\t\t\tDECLARE @intertbl2 TABLE (physical_name nvarchar(260))\r\n", "\t\t\t\tINSERT INTO @intertbl2\r\n", "\t\t\t\tSELECT physical_name\r\n", "\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2\r\n", "\t\t\t\t\tON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\tWHERE [database_id] = 2 AND LEN(t2.HD_Volume) > 3 AND [type] = 0\r\n", "\t\t\t-- select user DBs mountpoints only\r\n", "\t\t\t\tDECLARE @intertbl3 TABLE (physical_name nvarchar(260))\r\n", "\t\t\t\tINSERT INTO @intertbl3\r\n", "\t\t\t\tSELECT physical_name\r\n", "\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2\r\n", "\t\t\t\t\tON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\tWHERE [database_id] > 4 AND [database_id] <> 32767 AND LEN(t2.HD_Volume) > 3 AND [type] = 0\r\n", "\t\t\t-- select tempDB files in mountpoints\t\t\r\n", "\t\t\t\tDECLARE @tempDBtbl TABLE (database_id int,\r\n", "\t\t\t\t\ttype tinyint,\r\n", "\t\t\t\t\tfile_id int,\r\n", "\t\t\t\t\tphysical_name nvarchar(260),\r\n", "\t\t\t\t\tvolid smallint)\r\n", "\t\t\t\tINSERT INTO @tempDBtbl\r\n", "\t\t\t\t\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE [database_id] = 2 AND LEN(t2.HD_Volume) > 3 AND [type] = 0\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE [database_id] = 2 AND [type] = 0 AND physical_name NOT IN (SELECT physical_name\r\n", "\t\t\t\t\t\tFROM @intertbl2)\r\n", "\t\t\t-- select user DBs files in mountpoints\t\t\r\n", "\t\t\t\tDECLARE @otherstbl TABLE (database_id int,\r\n", "\t\t\t\t\ttype tinyint,\r\n", "\t\t\t\t\tfile_id int,\r\n", "\t\t\t\t\tphysical_name nvarchar(260),\r\n", "\t\t\t\t\tvolid smallint)\r\n", "\t\t\t\tINSERT INTO @otherstbl\r\n", "\t\t\t\t\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE [database_id] > 4 AND [database_id] <> 32767 AND LEN(t2.HD_Volume) > 3 AND [type] = 0\r\n", "\t\t\t\tUNION ALL\r\n", "\t\t\t\t\tSELECT database_id, type, file_id, physical_name, volid\r\n", "\t\t\t\t\tFROM sys.master_files t1 (NOLOCK) INNER JOIN @output_hw_format t2 ON LEFT(physical_name, LEN(t2.HD_Volume)) = RTRIM(t2.HD_Volume)\r\n", "\t\t\t\t\tWHERE [database_id] > 4 AND [database_id] <> 32767 AND [type] = 0 AND physical_name NOT IN (SELECT physical_name\r\n", "\t\t\t\t\t\tFROM @intertbl3)\r\n", "\t\t\t\tSELECT @ctr2 = COUNT(*)\r\n", "\t\t\t\tFROM @tempDBtbl\r\n", "\t\t\t\tWHERE LEFT(physical_name, 1) = \u0027C\u0027\r\n", "\t\t\t\tSELECT @ctr3 = COUNT(DISTINCT(t1.[database_id]))\r\n", "\t\t\t\tFROM @otherstbl t1 INNER JOIN @tempDBtbl t2 ON t1.volid = t2.volid;\r\n", "\t\t\t\tIF @ctr3 > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Check], \u0027[WARNING: tempDB is on the same physical volume as user databases]\u0027 AS [Deviation];\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE IF @ctr2 > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Check], \u0027[WARNING: tempDB is on C: drive]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tIF @ctr2 > 0 OR @ctr3 > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\t\t\t\t\tSELECT DISTINCT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Information], DB_NAME(mf.[database_id]) AS [Database_Name], type_desc AS [Type], mf.physical_name\r\n", "\t\t\t\t\t\tFROM sys.master_files mf (NOLOCK) INNER JOIN @otherstbl t1 ON mf.database_id = t1.database_id AND mf.physical_name = t1.physical_name\r\n", "\t\t\t\t\t\t\tINNER JOIN @tempDBtbl t2 ON t1.volid = t2.volid\r\n", "\t\t\t\t\tUNION ALL\r\n", "\t\t\t\t\t\tSELECT DISTINCT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Information], DB_NAME(mf.[database_id]) AS [Database_Name], type_desc AS [Type], mf.physical_name\r\n", "\t\t\t\t\t\tFROM sys.master_files mf (NOLOCK) INNER JOIN @tempDBtbl t1 ON mf.database_id = t1.database_id AND mf.physical_name = t1.physical_name\r\n", "\t\t\t\t\tORDER BY DB_NAME(mf.[database_id])\r\n", "\t\t\t\t\tOPTION\r\n", "\t\t\t\t\t(RECOMPILE);\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Database_checks\u0027 AS [Category], \u0027Data_and_Log_locations\u0027 AS [Check], \u0027[WARNING: Could not gather information on file locations]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_location\u0027 AS [Check], \u0027[WARNING: Could not gather information on file locations]\u0027 AS [Deviation]\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"Data files and Logs / tempDB and user Databases in same volume\" checks. A regular user can also run this check if a xp_cmdshell proxy account exists. Bypassing check]\u0027, 16, 1, N\u0027xp_cmdshellproxy\u0027)\r\n", "\t\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then must be a granted EXECUTE permissions on the following extended sprocs to run checks: sp_OACreate, sp_OADestroy, sp_OAGetErrorInfo, xp_cmdshell, xp_instance_regread, xp_regread, xp_fileexist and xp_regenumvalues. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "\t--RETURN\r\n", "\t\tEND\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"Data files and Logs / tempDB and user Databases in same volume\" check was skipped because xp_cmdshell was not allowed]\u0027, 10, 1, N\u0027disallow_xp_cmdshell\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "327f2c3a-b872-4fda-b116-ddad3b0fa355", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### tempDB data file configurations subsection\r\n" ], "metadata": { "azdata_cell_guid": "7056e093-a6be-484c-8adb-4ea1d2e947b8" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting tempDB data file configurations\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @tdb_files int, @online_count int, @filesizes smallint\r\n", "\tSELECT @tdb_files = COUNT(physical_name)\r\n", "\tFROM sys.master_files (NOLOCK)\r\n", "\tWHERE database_id = 2 AND [type] = 0;\r\n", "\tSELECT @online_count = COUNT(cpu_id)\r\n", "\tFROM sys.dm_os_schedulers\r\n", "\tWHERE is_online = 1 AND scheduler_id < 255 AND parent_node_id < 64;\r\n", "\tSELECT @filesizes = COUNT(DISTINCT size)\r\n", "\tFROM tempdb.sys.database_files\r\n", "\tWHERE [type] = 0;\r\n", "\tIF (SELECT CASE WHEN @filesizes = 1 AND ((@tdb_files >= 4 AND @tdb_files <= 8 AND @tdb_files % 4 = 0) /*OR (@tdb_files >= 8 AND @tdb_files % 4 = 0)*/\r\n", "\t\t\tOR (@tdb_files >= (@online_count / 2) AND @tdb_files >= 8 AND @tdb_files % 4 = 0)) THEN 0 ELSE 1 END) = 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files\u0027 AS [Information], physical_name AS [tempDB_Files], CAST((size*8)/1024.0 AS DECIMAL(18,2)) AS [File_Size_MB]\r\n", "\t\tFROM tempdb.sys.database_files (NOLOCK)\r\n", "\t\tWHERE type = 0;\r\n", "\tEND\r\n", "ELSE \r\n", "BEGIN\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files\u0027 AS [Check],\r\n", "\t\t\tCASE WHEN @tdb_files < 4 THEN \u0027[WARNING: tempDB has only \u0027 + CONVERT(VARCHAR(10), @tdb_files) + \u0027 file(s). Consider creating between 4 and 8 tempDB data files of the same size, with a minimum of 4]\u0027\r\n", "\t\t\tWHEN @filesizes = 1 AND @tdb_files < (@online_count / 2) AND @tdb_files >= 8 AND @tdb_files % 4 = 0 THEN \u0027[INFORMATION: Number of Data files to Scheduler ratio might not be Optimal. Consider creating 1 data file per each 2 cores, in multiples of 4, all of the same size]\u0027\r\n", "\t\t\tWHEN @filesizes > 1 AND @tdb_files >= 4 AND @tdb_files % 4 > 0 THEN \u0027[WARNING: Data file sizes do not match and Number of data files is not multiple of 4]\u0027\r\n", "\t\t\tWHEN @filesizes = 1 AND @tdb_files >= 4 AND @tdb_files % 4 > 0 THEN \u0027[WARNING: Number of data files is not multiple of 4]\u0027\r\n", "\t\t\tWHEN @filesizes > 1 AND @tdb_files >= 4 AND @tdb_files % 4 = 0 THEN \u0027[WARNING: Data file sizes do not match]\u0027\r\n", "\t\t\tELSE \u0027[OK]\u0027 END AS [Deviation];\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files\u0027 AS [Information], physical_name AS [tempDB_Files], CAST((size*8)/1024.0 AS DECIMAL(18,2)) AS [File_Size_MB]\r\n", "\t\tFROM tempdb.sys.database_files (NOLOCK)\r\n", "\t\tWHERE type = 0;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "18a39c66-bf3f-4649-a442-7ab7e27b4349", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### tempDB data files autogrow of equal size subsection\r\n" ], "metadata": { "azdata_cell_guid": "b33ab6de-5445-4f83-aa92-6213dcdf2c95" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting tempDB Files autogrow of equal size\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(DISTINCT growth)\r\n", "\t\tFROM sys.master_files\r\n", "\t\tWHERE [database_id] = 2 AND [type] = 0) > 1\r\n", "\t\tOR (SELECT COUNT(DISTINCT is_percent_growth)\r\n", "\t\tFROM sys.master_files\r\n", "\t\tWHERE [database_id] = 2 AND [type] = 0) > 1\r\n", "BEGIN\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files_Autogrow\u0027 AS [Check], \u0027[WARNING: Some tempDB data files have different growth settings]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files_Autogrow\u0027 AS [Information],\r\n", "\t\t\tDB_NAME(2) AS [Database_Name],\r\n", "\t\t\tmf.name AS [Logical_Name],\r\n", "\t\t\tmf.[size]*8 AS [Current_Size_KB],\r\n", "\t\t\tmf.type_desc AS [File_Type],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN \u0027pct\u0027 ELSE \u0027pages\u0027 END AS [Growth_Type],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 THEN mf.growth ELSE mf.growth*8 END AS [Growth_Amount],\r\n", "\t\t\tCASE WHEN is_percent_growth = 1 AND mf.growth > 0 THEN ((mf.size*8)*CONVERT(bigint, mf.growth))/100 \r\n", "\t\t\tWHEN is_percent_growth = 0 AND mf.growth > 0 THEN mf.growth*8 \r\n", "\t\t\tELSE 0 END AS [Next_Growth_KB],\r\n", "\t\t\tCASE WHEN @ifi = 0 AND mf.type = 0 THEN \u0027Instant File Initialization is disabled\u0027\r\n", "\t\t\tWHEN @ifi = 1 AND mf.type = 0 THEN \u0027Instant File Initialization is enabled\u0027\r\n", "\t\t\tELSE \u0027\u0027 END AS [Comments]\r\n", "\t\tFROM tempdb.sys.database_files mf (NOLOCK)\r\n", "\t\tWHERE [type] = 0\r\n", "\t\tGROUP BY mf.name, mf.[size], is_percent_growth, mf.growth, mf.type_desc, mf.[type]\r\n", "\t\tORDER BY 3, 4\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027tempDB_checks\u0027 AS [Category], \u0027tempDB_files_Autogrow\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "f09aec3c-079a-4bb0-aad0-8ead50ddea59", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Perf counters, Waits, Latches and Spinlocks subsection\r\n", "You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "You can set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. \r\n", "- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n" ], "metadata": { "azdata_cell_guid": "15e6af11-5a25-43e4-b178-1cbd59f90f6d" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "RAISERROR (N\u0027|-Starting Performance Checks\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tSELECT @ErrorMessage = \u0027 |-Starting Perf counters, Waits and Latches (wait for \u0027 + CONVERT(VARCHAR(3), @duration) + \u0027s)\u0027\r\n", "\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE @minctr DATETIME, @maxctr DATETIME, @durationstr NVARCHAR(24)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerfCount\u0027))\r\n", "\tDROP TABLE #tblPerfCount;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerfCount\u0027))\r\n", "\tCREATE TABLE #tblPerfCount\r\n", "\t\t(\r\n", "\t\t\t[retrieval_time] [datetime],\r\n", "\t\t\t[object_name] [NVARCHAR](128),\r\n", "\t\t\t[counter_name] [NVARCHAR](128),\r\n", "\t\t\t[instance_name] [NVARCHAR](128),\r\n", "\t\t\t[counter_name_type] int,\r\n", "\t\t\t[cntr_value] float NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblPerfThresholds\u0027))\r\n", "\tDROP TABLE tempdb.dbo.tblPerfThresholds;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblPerfThresholds\u0027))\r\n", "\tCREATE TABLE tempdb.dbo.tblPerfThresholds\r\n", "\t\t(\r\n", "\t\t\t[counter_family] [NVARCHAR](128),\r\n", "\t\t\t[counter_name] [NVARCHAR](128),\r\n", "\t\t\t[counter_instance] [NVARCHAR](128),\r\n", "\t\t\t[counter_name_type] int,\r\n", "\t\t\t[counter_value] float NULL\r\n", "\t\t);\r\n", "\t-- Create the helper function\r\n", "\t\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_perfctr\u0027\u0027)) DROP FUNCTION dbo.fn_perfctr\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; EXEC(\u0027\u0027\r\n", "CREATE FUNCTION dbo.fn_perfctr (@ctr1Fam NVARCHAR(128), @ctr1 NVARCHAR(128))\r\n", "RETURNS float\r\n", "AS\r\n", "BEGIN\r\n", "\tDECLARE @ReturnVals float, @ctr1Val float, @ctr2Val float, @ctr2Fam NVARCHAR(128), @ctr2 NVARCHAR(128), @type tinyint\r\n", "\t\r\n", "-- ctr1Fam = source counter object; ctr1 = source counter; ctr2Fam = counter object to compare with; ctr2 = counter to compare with\r\n", "-- Type 1 = ratio between source and compare (Ex. 1 per each 10); 2 = pct ratio between source and compare (Ex. 10 pct of compare counter); 3 = ratio between compare and source; 4 = pct ratio between compare and source\r\n", "\tIF @ctr1 IN (\u0027\u0027\u0027\u0027Forwarded Records/sec\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027FreeSpace Scans/sec\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027Page Splits/sec\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027Workfiles Created/sec\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027Page lookups/sec\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027SQL Compilations/sec\u0027\u0027\u0027\u0027) \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:SQL Statistics\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Batch Requests/sec\u0027\u0027\u0027\u0027, @type = 1 \r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Lock Requests/sec\u0027\u0027\u0027\u0027\r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:SQL Statistics\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Batch Requests/sec\u0027\u0027\u0027\u0027, @type = 0\r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Full Scans/sec\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:Access Methods\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Index Searches/sec\u0027\u0027\u0027\u0027, @type = 1\r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Index Searches/sec\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:Access Methods\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Full Scans/sec\u0027\u0027\u0027\u0027, @type = 3 \r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Readahead pages/sec\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:Buffer Manager\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Page reads/sec\u0027\u0027\u0027\u0027, @type = 1\r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Target Server Memory (KB)\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:Memory Manager\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Total Server Memory (KB)\u0027\u0027\u0027\u0027, @type = 2\r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027SQL Re-Compilations/sec\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:SQL Statistics\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027SQL Compilations/sec\u0027\u0027\u0027\u0027, @type = 1\r\n", "\tELSE IF @ctr1 = \u0027\u0027\u0027\u0027Page writes/sec\u0027\u0027\u0027\u0027 \r\n", "\t\tSELECT @ctr2Fam = \u0027\u0027\u0027\u0027SQLServer:Buffer Manager\u0027\u0027\u0027\u0027, @ctr2 = \u0027\u0027\u0027\u0027Page reads/sec\u0027\u0027\u0027\u0027, @type = 3\r\n", "\tSELECT @ctr1Val = [counter_value] FROM tempdb.dbo.tblPerfThresholds WHERE [counter_family] = @ctr1Fam AND [counter_name] = @ctr1\r\n", "\tSELECT @ctr2Val = [counter_value] FROM tempdb.dbo.tblPerfThresholds WHERE [counter_family] = @ctr2Fam AND [counter_name] = @ctr2\r\n", "\tIF @ctr1 = \u0027\u0027\u0027\u0027Target Server Memory (KB)\u0027\u0027\u0027\u0027\r\n", "\tSELECT @ctr1Val = @ctr1Val / 1024, @ctr2Val = @ctr2Val / 1024\r\n", "\t\r\n", "--Find ratio between counter 1 and 2\r\n", "\tIF @ctr1Val IS NULL OR @ctr2Val IS NULL\r\n", "\tBEGIN\r\n", "\t\tSELECT @ReturnVals = NULL\r\n", "\tEND\r\n", "\tELSE IF @ctr1Val > 1 AND @ctr2Val > 1\r\n", "\tBEGIN\r\n", "\t\tIF @type = 0\r\n", "\t\tSELECT @ReturnVals = (@ctr1Val / @ctr2Val)\r\n", "\t\tIF @type = 1\r\n", "\t\tSELECT @ReturnVals = (@ctr1Val / @ctr2Val) * 100\r\n", "\t\tIf @type = 2\r\n", "\t\tSELECT @ReturnVals = (@ctr1Val - @ctr2Val)\r\n", "\t\tIF @type = 3\r\n", "\t\tSELECT @ReturnVals = (@ctr2Val / @ctr1Val) * 100\r\n", "\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\tSELECT @ReturnVals = 0\r\n", "\tEND\r\n", "\tRETURN (@ReturnVals)\r\n", "END\u0027\u0027)\r\n", "\t\u0027)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWaits\u0027))\r\n", "\tDROP TABLE #tblWaits;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWaits\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblWaits]\r\n", "\t\t(\r\n", "\t\t\t[retrieval_time] [datetime],\r\n", "\t\t\t[wait_type] [nvarchar](60) NOT NULL,\r\n", "\t\t\t[wait_time_ms] bigint NULL,\r\n", "\t\t\t[signal_wait_time_ms] bigint NULL,\r\n", "\t\t\t[resource_wait_time_ms] bigint NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalWaits\u0027))\r\n", "\tDROP TABLE #tblFinalWaits;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalWaits\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblFinalWaits]\r\n", "\t\t(\r\n", "\t\t\t[wait_type] [nvarchar](60) NOT NULL,\r\n", "\t\t\t[wait_time_s] [numeric](16, 6) NULL,\r\n", "\t\t\t[signal_wait_time_s] [numeric](16, 6) NULL,\r\n", "\t\t\t[resource_wait_time_s] [numeric](16, 6) NULL,\r\n", "\t\t\t[pct] [numeric](12, 2) NULL,\r\n", "\t\t\t[rn] [bigint] NULL,\r\n", "\t\t\t[signal_wait_pct] [numeric](12, 2) NULL,\r\n", "\t\t\t[resource_wait_pct] [numeric](12, 2) NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblLatches\u0027))\r\n", "\tDROP TABLE #tblLatches;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblLatches\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblLatches]\r\n", "\t\t(\r\n", "\t\t\t[retrieval_time] [datetime],\r\n", "\t\t\t[latch_class] [nvarchar](60) NOT NULL,\r\n", "\t\t\t[wait_time_ms] bigint NULL,\r\n", "\t\t\t[waiting_requests_count] [bigint] NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalLatches\u0027))\r\n", "\tDROP TABLE #tblFinalLatches;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalLatches\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblFinalLatches]\r\n", "\t\t(\r\n", "\t\t\t[latch_class] [nvarchar](60) NOT NULL,\r\n", "\t\t\t[wait_time_s] [decimal](16, 6) NULL,\r\n", "\t\t\t[waiting_requests_count] [bigint] NULL,\r\n", "\t\t\t[pct] [decimal](12, 2) NULL,\r\n", "\t\t\t[rn] [bigint] NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksBefore\u0027))\r\n", "\tDROP TABLE #tblSpinlocksBefore;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksBefore\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblSpinlocksBefore]\r\n", "\t\t(\r\n", "\t\t\t[name] NVARCHAR(512) NOT NULL,\r\n", "\t\t\t[collisions] bigint NULL,\r\n", "\t\t\t[spins] bigint NULL,\r\n", "\t\t\t[spins_per_collision] real NULL,\r\n", "\t\t\t[sleep_time] bigint NULL,\r\n", "\t\t\t[backoffs] int NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksAfter\u0027))\r\n", "\tDROP TABLE #tblSpinlocksAfter;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksAfter\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblSpinlocksAfter]\r\n", "\t\t(\r\n", "\t\t\t[name] NVARCHAR(512) NOT NULL,\r\n", "\t\t\t[collisions] bigint NULL,\r\n", "\t\t\t[spins] bigint NULL,\r\n", "\t\t\t[spins_per_collision] real NULL,\r\n", "\t\t\t[sleep_time] bigint NULL,\r\n", "\t\t\t[backoffs] int NULL\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalSpinlocks\u0027))\r\n", "\tDROP TABLE #tblFinalSpinlocks;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalSpinlocks\u0027))\r\n", "\tCREATE TABLE [dbo].[#tblFinalSpinlocks]\r\n", "\t\t(\r\n", "\t\t\t[name] NVARCHAR(512) NOT NULL,\r\n", "\t\t\t[collisions] bigint NULL,\r\n", "\t\t\t[spins] bigint NULL,\r\n", "\t\t\t[spins_per_collision] real NULL,\r\n", "\t\t\t[sleep_time] bigint NULL,\r\n", "\t\t\t[backoffs] int NULL,\r\n", "\t\t\t[spins_pct] [decimal](12, 2) NULL,\r\n", "\t\t\t[rn] [bigint] NULL\r\n", "\t\t);\r\n", "\t\tSELECT @minctr = GETDATE()\r\n", "\t-- When counter type = 272696576 (find delta from two collection points)\r\n", "\t-- When counter type = 65792 (face value)\r\n", "\t-- When counter type = 1073939712 (base value, check next counter types)\r\n", "\t-- When counter type = 1073874176 (find delta from current value and base value between two collection points). Base value is counter with type 1073939712.\r\n", "\t-- When counter type = 537003264 (find delta from current value and base value). Base value is counter with type 1073939712.\r\n", "\t\tINSERT INTO #tblPerfCount\r\n", "\t\tSELECT @minctr, [object_name], counter_name, instance_name, cntr_type AS counter_name_type, cntr_value\r\n", "\t\tFROM sys.dm_os_performance_counters pc0 (NOLOCK)\r\n", "\t\tWHERE ([object_name] LIKE \u0027%:Access Methods%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Buffer Manager%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Buffer Node%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Latches%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Locks%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Manager%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Node%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Plan Cache%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:SQL Statistics%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Wait Statistics%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Workload Group Stats%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Broker Clerks%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Databases%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Database Replica%\u0027)\r\n", "\t\t\tAND (counter_name LIKE \u0027%FreeSpace Scans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Forwarded Records/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Full Scans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Index Searches/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page Splits/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Scan Point Revalidations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Table Lock Escalations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Workfiles Created/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Worktables Created/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Worktables From Cache%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Buffer cache hit ratio%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Buffer cache hit ratio base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Checkpoint pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Background writer pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Lazy writes/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free pages%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page life expectancy%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page lookups/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page reads/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page writes/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Readahead pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Latch Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Latch Wait Time Base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Latch Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Wait Time Base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Number of Deadlocks/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Stolen Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Target Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Foreign Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Stolen Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Target Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Batch Requests/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Compilations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Re-Compilations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Lock waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log buffer waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log write waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Memory grant queue waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Network IO waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Non-Page latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page IO latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Active parallel threads%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Blocked tasks%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%CPU usage %\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%CPU usage % base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Query optimizations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Requests completed/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Suboptimal plans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Temporary Tables \u0026 Table Variables%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Extended Stored Procedures%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Bound Trees%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Plans%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Object Plans%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%_Total%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027Transactions/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Flush Wait Time%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Flush Waits/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Recovery Queue%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Send Queue%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Transaction Delay%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Redo blocked/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Resent Messages/sec%\u0027\r\n", "\t\t\tOR instance_name LIKE \u0027%Buffer Pool%\u0027\r\n", "\t\t\tOR instance_name LIKE \u0027%Column store object pool%\u0027);\r\n", "\t\tINSERT INTO #tblWaits\r\n", "\t\tSELECT @minctr, wait_type, wait_time_ms, signal_wait_time_ms, (wait_time_ms-signal_wait_time_ms) AS resource_wait_time_ms\r\n", "\t\tFROM sys.dm_os_wait_stats (NOLOCK)\r\n", "\t\tWHERE wait_type NOT IN (\u0027RESOURCE_QUEUE\u0027, \u0027SQLTRACE_INCREMENTAL_FLUSH_SLEEP\u0027, \r\n", "\t\u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027,\r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027LOGMGR_QUEUE\u0027,\u0027CHECKPOINT_QUEUE\u0027,\u0027REQUEST_FOR_DEADLOCK_SEARCH\u0027,\u0027XE_TIMER_EVENT\u0027,\r\n", "\t\u0027BROKER_TASK_STOP\u0027,\u0027CLR_MANUAL_EVENT\u0027, \u0027CLR_AUTO_EVENT\u0027,\u0027DISPATCHER_QUEUE_SEMAPHORE\u0027, \u0027FT_IFTS_SCHEDULER_IDLE_WAIT\u0027,\u0027BROKER_TO_FLUSH\u0027,\r\n", "\t\u0027XE_DISPATCHER_WAIT\u0027, \u0027XE_DISPATCHER_JOIN\u0027, \u0027MSQL_XP\u0027, \u0027WAIT_FOR_RESULTS\u0027, \u0027CLR_SEMAPHORE\u0027, \u0027LAZYWRITER_SLEEP\u0027, \u0027SLEEP_TASK\u0027,\r\n", "\t\u0027SLEEP_SYSTEMTASK\u0027, \u0027SQLTRACE_BUFFER_FLUSH\u0027, \u0027WAITFOR\u0027, \u0027BROKER_EVENTHANDLER\u0027, \u0027TRACEWRITE\u0027, \u0027FT_IFTSHC_MUTEX\u0027, \u0027BROKER_RECEIVE_WAITFOR\u0027, \r\n", "\t\u0027ONDEMAND_TASK_QUEUE\u0027, \u0027DBMIRROR_EVENTS_QUEUE\u0027, \u0027DBMIRRORING_CMD\u0027, \u0027BROKER_TRANSMITTER\u0027, \u0027SQLTRACE_WAIT_ENTRIES\u0027, \u0027SLEEP_BPOOL_FLUSH\u0027, \u0027SQLTRACE_LOCK\u0027,\r\n", "\t\u0027DIRTY_PAGE_POLL\u0027, \u0027HADR_FILESTREAM_IOMGR_IOCOMPLETION\u0027, \u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027, \r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027WAIT_XTP_OFFLINE_CKPT_NEW_LOG\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027)\r\n", "\t\t\tAND wait_type NOT LIKE N\u0027SLEEP_%\u0027\r\n", "\t\t\tAND wait_time_ms > 0;\r\n", "\t\tINSERT INTO #tblLatches\r\n", "\t\tSELECT @minctr, latch_class, wait_time_ms, waiting_requests_count\r\n", "\t\tFROM sys.dm_os_latch_stats (NOLOCK)\r\n", "\t\tWHERE /*latch_class NOT IN (\u0027BUFFER\u0027)\r\n", "\t\tAND*/ wait_time_ms > 0;\r\n", "\t\tIF @sqlmajorver > 9\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblSpinlocksBefore\r\n", "\t\t\tSELECT name, collisions, spins, spins_per_collision, sleep_time, backoffs\r\n", "\t\t\tFROM sys.dm_os_spinlock_stats;\r\n", "\t\tEND\r\n", "\tELSE IF @sqlmajorver = 9\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblSpinlocksBefore\r\n", "\t\t\tEXEC (\u0027DBCC SQLPERF(\u0027\u0027spinlockstats\u0027\u0027)\u0027);\r\n", "\t\tEND;\r\n", "\t\tIF @duration > 255\r\n", "\tSET @duration = 255;\r\n", "\t\tIF @duration < 10\r\n", "\tSET @duration = 10;\r\n", "\t\tSELECT @durationstr = \u0027WAITFOR DELAY \u0027\u002700:\u0027 + CASE WHEN LEN(CONVERT(VARCHAR(3),@duration/60%60)) = 1 \r\n", "\t\tTHEN \u00270\u0027 + CONVERT(VARCHAR(3),@duration/60%60) \r\n", "\t\t\tELSE CONVERT(VARCHAR(3),@duration/60%60) END \r\n", "\t\t+ \u0027:\u0027 + CONVERT(VARCHAR(3),@duration-(@duration/60)*60) + \u0027\u0027\u0027\u0027\r\n", "\t\tEXECUTE sp_executesql @durationstr;\r\n", "\t\tSELECT @maxctr = GETDATE()\r\n", "\t\tINSERT INTO #tblPerfCount\r\n", "\t\tSELECT @maxctr, [object_name], counter_name, instance_name, cntr_type AS counter_name_type, cntr_value\r\n", "\t\tFROM sys.dm_os_performance_counters pc0 (NOLOCK)\r\n", "\t\tWHERE (cntr_type = 272696576 OR cntr_type = 1073874176 OR cntr_type = 1073939712) -- Get only counters whose delta between collection points matters\r\n", "\t\t\tAND ([object_name] LIKE \u0027%:Access Methods%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Buffer Manager%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Buffer Node%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Latches%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Locks%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Manager%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Node%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Plan Cache%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:SQL Statistics%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Wait Statistics%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Workload Group Stats%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Memory Broker Clerks%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Databases%\u0027\r\n", "\t\t\tOR [object_name] LIKE \u0027%:Database Replica%\u0027)\r\n", "\t\t\tAND (counter_name LIKE \u0027%FreeSpace Scans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Forwarded Records/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Full Scans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Index Searches/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page Splits/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Scan Point Revalidations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Table Lock Escalations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Workfiles Created/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Worktables Created/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Worktables From Cache%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Buffer cache hit ratio%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Buffer cache hit ratio base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Checkpoint pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Background writer pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Lazy writes/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free pages%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page life expectancy%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page lookups/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page reads/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page writes/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Readahead pages/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Latch Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Latch Wait Time Base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Latch Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Wait Time (ms)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Average Wait Time Base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Number of Deadlocks/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Stolen Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Target Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Server Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Free Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Foreign Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Stolen Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Target Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Total Node Memory (KB)%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Batch Requests/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Compilations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Re-Compilations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Lock waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log buffer waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log write waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Memory grant queue waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Network IO waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Non-Page latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page IO latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Page latch waits%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Active parallel threads%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Blocked tasks%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%CPU usage %\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%CPU usage % base%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Query optimizations/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Requests completed/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Suboptimal plans/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Temporary Tables \u0026 Table Variables%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Extended Stored Procedures%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Bound Trees%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%SQL Plans%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Object Plans%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%_Total%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027Transactions/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Flush Wait Time%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Flush Waits/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Recovery Queue%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Log Send Queue%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Transaction Delay%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Redo blocked/sec%\u0027\r\n", "\t\t\tOR counter_name LIKE \u0027%Resent Messages/sec%\u0027\r\n", "\t\t\tOR instance_name LIKE \u0027%Buffer Pool%\u0027\r\n", "\t\t\tOR instance_name LIKE \u0027%Column store object pool%\u0027);\r\n", "\t\tINSERT INTO #tblWaits\r\n", "\t\tSELECT @maxctr, wait_type, wait_time_ms, signal_wait_time_ms, (wait_time_ms-signal_wait_time_ms) AS resource_wait_time_ms\r\n", "\t\tFROM sys.dm_os_wait_stats (NOLOCK)\r\n", "\t\tWHERE wait_type NOT IN (\u0027RESOURCE_QUEUE\u0027, \u0027SQLTRACE_INCREMENTAL_FLUSH_SLEEP\u0027, \r\n", "\t\u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027,\r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027LOGMGR_QUEUE\u0027,\u0027CHECKPOINT_QUEUE\u0027,\u0027REQUEST_FOR_DEADLOCK_SEARCH\u0027,\u0027XE_TIMER_EVENT\u0027,\r\n", "\t\u0027BROKER_TASK_STOP\u0027,\u0027CLR_MANUAL_EVENT\u0027, \u0027CLR_AUTO_EVENT\u0027,\u0027DISPATCHER_QUEUE_SEMAPHORE\u0027, \u0027FT_IFTS_SCHEDULER_IDLE_WAIT\u0027,\u0027BROKER_TO_FLUSH\u0027,\r\n", "\t\u0027XE_DISPATCHER_WAIT\u0027, \u0027XE_DISPATCHER_JOIN\u0027, \u0027MSQL_XP\u0027, \u0027WAIT_FOR_RESULTS\u0027, \u0027CLR_SEMAPHORE\u0027, \u0027LAZYWRITER_SLEEP\u0027, \u0027SLEEP_TASK\u0027,\r\n", "\t\u0027SLEEP_SYSTEMTASK\u0027, \u0027SQLTRACE_BUFFER_FLUSH\u0027, \u0027WAITFOR\u0027, \u0027BROKER_EVENTHANDLER\u0027, \u0027TRACEWRITE\u0027, \u0027FT_IFTSHC_MUTEX\u0027, \u0027BROKER_RECEIVE_WAITFOR\u0027, \r\n", "\t\u0027ONDEMAND_TASK_QUEUE\u0027, \u0027DBMIRROR_EVENTS_QUEUE\u0027, \u0027DBMIRRORING_CMD\u0027, \u0027BROKER_TRANSMITTER\u0027, \u0027SQLTRACE_WAIT_ENTRIES\u0027, \u0027SLEEP_BPOOL_FLUSH\u0027, \u0027SQLTRACE_LOCK\u0027,\r\n", "\t\u0027DIRTY_PAGE_POLL\u0027, \u0027HADR_FILESTREAM_IOMGR_IOCOMPLETION\u0027, \u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027, \r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027WAIT_XTP_OFFLINE_CKPT_NEW_LOG\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027)\r\n", "\t\t\tAND wait_type NOT LIKE N\u0027SLEEP_%\u0027\r\n", "\t\t\tAND wait_time_ms > 0;\r\n", "\t\tINSERT INTO #tblLatches\r\n", "\t\tSELECT @maxctr, latch_class, wait_time_ms, waiting_requests_count\r\n", "\t\tFROM sys.dm_os_latch_stats (NOLOCK)\r\n", "\t\tWHERE /*latch_class NOT IN (\u0027BUFFER\u0027)\r\n", "\t\tAND*/ wait_time_ms > 0;\r\n", "\t\tIF @sqlmajorver > 9\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblSpinlocksAfter\r\n", "\t\t\tSELECT name, collisions, spins, spins_per_collision, sleep_time, backoffs\r\n", "\t\t\tFROM sys.dm_os_spinlock_stats;\r\n", "\t\tEND\r\n", "\tELSE IF @sqlmajorver = 9\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #tblSpinlocksAfter\r\n", "\t\t\tEXEC (\u0027DBCC SQLPERF(\u0027\u0027spinlockstats\u0027\u0027)\u0027);\r\n", "\t\tEND;\r\n", "\t\tINSERT INTO tempdb.dbo.tblPerfThresholds\r\n", "\t\tSELECT DISTINCT t1.[object_name], t1.counter_name, t1.instance_name, t1.[counter_name_type],\r\n", "\t\t\tCASE WHEN t1.counter_name_type = 272696576\r\n", "\t\t\tTHEN CONVERT(float,(\r\n", "\t\t\t(SELECT t2.cntr_value\r\n", "\t\t\tFROM #tblPerfCount t2\r\n", "\t\t\tWHERE t2.[retrieval_time] = @maxctr AND t2.counter_name = t1.counter_name AND t2.instance_name = t1.instance_name) -\r\n", "\t\t\t(SELECT t2.cntr_value\r\n", "\t\t\tFROM #tblPerfCount t2\r\n", "\t\t\tWHERE t2.[retrieval_time] = @minctr AND t2.counter_name = t1.counter_name AND t2.instance_name = t1.instance_name)\r\n", "\t\t\t) / DATEDIFF(ss,@minctr,@maxctr)) -- Get value per s over last xx s\r\n", "\t\tWHEN t1.counter_name_type = 537003264\r\n", "\t\t\tTHEN (SELECT CONVERT(float,(t2.cntr_value / CASE WHEN t3.cntr_value <= 0 THEN 1 ELSE t3.cntr_value END) * 100.0)\r\n", "\t\t\tFROM #tblPerfCount t2 INNER JOIN #tblPerfCount t3 ON t2.[object_name] = t3.[object_name] AND t2.instance_name = t3.instance_name AND t3.counter_name IN (RTRIM(t2.counter_name) + N\u0027 base\u0027, \u0027Worktables From Cache Base\u0027)\r\n", "\t\t\tWHERE t2.counter_name_type = t1.counter_name_type AND t3.counter_name_type = 1073939712 AND t2.counter_name = t1.counter_name AND t2.instance_name = t1.instance_name AND t2.[retrieval_time] = @minctr AND t3.[retrieval_time] = @minctr\r\n", "\t\t\tGROUP BY t2.[retrieval_time], t2.cntr_value, t3.cntr_value, t2.counter_name)\r\n", "\t\tWHEN t1.counter_name_type = 1073874176 AND t1.counter_name = \u0027Average Latch Wait Time (ms)\u0027\r\n", "\t\t\tTHEN CONVERT(float,(\r\n", "\t\t\t(\r\n", "\t\t\t(SELECT t2.cntr_value - t3.cntr_value\r\n", "\t\t\tFROM #tblPerfCount t2 INNER JOIN #tblPerfCount t3 ON t2.[object_name] = t3.[object_name] AND t2.counter_name = t3.counter_name\r\n", "\t\t\tWHERE t2.counter_name = t1.counter_name /*AND t2.counter_name_type = t1.counter_name_type AND t2.instance_name = t1.instance_name*/ AND t2.[retrieval_time] = @maxctr AND t3.[retrieval_time] = @minctr\r\n", "\t\t\tGROUP BY t2.[retrieval_time], t2.cntr_value, t3.cntr_value, t2.counter_name)\r\n", "\t\t\t/\r\n", "\t\t\t(SELECT CASE WHEN t2.cntr_value - t3.cntr_value <= 0 THEN 1 ELSE t2.cntr_value - t3.cntr_value END\r\n", "\t\t\tFROM #tblPerfCount t2 INNER JOIN #tblPerfCount t3 ON t2.[object_name] = t3.[object_name] AND t2.counter_name = t3.counter_name\r\n", "\t\t\tWHERE t2.counter_name = \u0027Average Latch Wait Time Base\u0027 AND t2.counter_name_type = 1073939712 AND t2.instance_name = t1.instance_name AND t2.[retrieval_time] = @maxctr AND t3.[retrieval_time] = @minctr\r\n", "\t\t\tGROUP BY t2.[retrieval_time], t2.cntr_value, t3.cntr_value, t2.counter_name)\r\n", "\t\t\t)\r\n", "\t\t\t/ DATEDIFF(ss,@minctr,@maxctr))) -- Get value per s over last xx s\r\n", "\t\tWHEN t1.counter_name_type = 1073874176 AND t1.counter_name = \u0027Average Wait Time (ms)\u0027\r\n", "\t\t\tTHEN CONVERT(float,(\r\n", "\t\t\t(\r\n", "\t\t\tSELECT (t4.cntr_value / CASE WHEN t5.cntr_value <= 0 THEN 1 ELSE t5.cntr_value END) / DATEDIFF(ss,@minctr,@maxctr)\r\n", "\t\t\tFROM\r\n", "\t\t\t\t(SELECT t2.cntr_value - t3.cntr_value AS cntr_value, t2.instance_name\r\n", "\t\t\t\tFROM #tblPerfCount t2 INNER JOIN #tblPerfCount t3 ON t2.[object_name] = t3.[object_name] AND t2.counter_name = t3.counter_name AND t2.instance_name = t3.instance_name\r\n", "\t\t\t\tWHERE t2.counter_name = t1.counter_name /*AND t2.counter_name_type = t1.counter_name_type AND t2.instance_name = t1.instance_name*/ AND t2.[retrieval_time] = @maxctr AND t3.[retrieval_time] = @minctr\r\n", "\t\t\t\tGROUP BY t2.[retrieval_time], t2.cntr_value, t3.cntr_value, t2.counter_name, t2.instance_name) AS t4\r\n", "\t\t\t\tINNER JOIN\r\n", "\t\t\t\t(SELECT t2.cntr_value - t3.cntr_value AS cntr_value, t2.instance_name\r\n", "\t\t\t\tFROM #tblPerfCount t2 INNER JOIN #tblPerfCount t3 ON t2.[object_name] = t3.[object_name] AND t2.counter_name = t3.counter_name AND t2.instance_name = t3.instance_name\r\n", "\t\t\t\tWHERE t2.counter_name = \u0027Average Wait Time Base\u0027 AND t2.counter_name_type = 1073939712 AND t2.instance_name = t1.instance_name AND t2.[retrieval_time] = @maxctr AND t3.[retrieval_time] = @minctr\r\n", "\t\t\t\tGROUP BY t2.[retrieval_time], t2.cntr_value, t3.cntr_value, t2.counter_name, t2.instance_name) AS t5\r\n", "\t\t\t\tON t4.instance_name = t5.instance_name\r\n", "\t\t\t))) -- Get value per s over last xx s\r\n", "\t\tELSE CONVERT(float,t1.cntr_value)\r\n", "\tEND\r\n", "\t\tFROM #tblPerfCount t1\r\n", "\t\tWHERE (t1.counter_name_type <> 1073939712)\r\n", "\t\tGROUP BY t1.[object_name], t1.[counter_name], t1.instance_name, t1.counter_name_type, t1.cntr_value\r\n", "\t\tORDER BY t1.[object_name], t1.[counter_name], t1.instance_name;\r\n", "\t\t;WITH\r\n", "\t\t\tctectr\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT [counter_family], [counter_name], [counter_instance], [counter_value],\r\n", "\t\t\t\t\tCASE WHEN [counter_name] IN (\u0027Worktables Created/sec\u0027,\u0027Worktables From Cache Ratio\u0027,\u0027Buffer cache hit ratio\u0027,\r\n", "\t\t\t\t\u0027Free list stalls/sec\u0027,\u0027Free pages\u0027,\u0027Free Memory (KB)\u0027,\u0027Lazy writes/sec\u0027,\u0027Page life expectancy\u0027,\r\n", "\t\t\t\t\u0027Page reads/sec\u0027,\u0027Log Flush Wait Time\u0027,\u0027Log Flush Waits/sec\u0027,\u0027Average Latch Wait Time (ms)\u0027,\r\n", "\t\t\t\t\u0027Total Latch Wait Time (ms)\u0027,\u0027Lock Waits/sec\u0027,\u0027Number of Deadlocks/sec\u0027,\u0027Batch Requests/sec\u0027) THEN [counter_value] \r\n", "\t\t\tELSE tempdb.dbo.fn_perfctr([counter_family],[counter_name]) END AS [counter_calculated_threshold_value]\r\n", "\t\t\t\tFROM tempdb.dbo.tblPerfThresholds\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Perf_Counters\u0027 AS [Check], [counter_family], [counter_name], [counter_instance], [counter_value], [counter_calculated_threshold_value],\r\n", "\t\t\tCASE WHEN [counter_name] = \u0027Forwarded Records/sec\u0027 AND [counter_calculated_threshold_value] > 10 THEN \u0027[WARNING: A ratio of more than 1 forwarded record for every 10 batch requests]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027FreeSpace Scans/sec\u0027 AND [counter_calculated_threshold_value] > 10 THEN \u0027[WARNING: A ratio of more than 1 freespace scan for every 10 batch requests]\u0027\r\n", "\t\t\tWHEN [counter_name] IN (\u0027Full Scans/sec\u0027,\u0027Index Searches/sec\u0027) AND [counter_calculated_threshold_value] > 0.1 THEN \u0027[WARNING: A ratio of more than 1 SQL Full Scan for every 1000 Index Searches]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page Splits/sec\u0027 AND [counter_calculated_threshold_value] > 5 THEN \u0027[WARNING: A ratio of more than 1 page split for every 20 batch requests]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Workfiles Created/sec\u0027 AND [counter_calculated_threshold_value] > 5 THEN \u0027[WARNING: A ratio of more than 1 workfile created for every 20 batch requests]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Worktables Created/sec\u0027 AND [counter_calculated_threshold_value] > 20 THEN \u0027[WARNING: Greater than 20 Worktables created per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Worktables From Cache Ratio\u0027 AND [counter_calculated_threshold_value] < 90 THEN \u0027[WARNING: Less than 90 percent Worktables from Cache Ratio]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Buffer cache hit ratio\u0027 AND [counter_calculated_threshold_value] < 97 THEN \u0027[WARNING: Less than 97 percent buffer cache hit ratio]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Buffer cache hit ratio\u0027 AND [counter_calculated_threshold_value] < 90 THEN \u0027[WARNING: Less than 90 percent buffer cache hit ratio]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Free list stalls/sec\u0027 AND [counter_calculated_threshold_value] < 2 THEN \u0027[WARNING: Free list stalls per second is less than 2]\u0027 \r\n", "\t\t\tWHEN [counter_name] = \u0027Free pages\u0027 AND [counter_calculated_threshold_value] < 640 THEN \u0027[WARNING: Less than 640 Free Pages]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Free Memory (KB)\u0027 AND [counter_calculated_threshold_value] < 5 THEN \u0027[WARNING: Less than 5MB]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Lazy writes/sec\u0027 AND [counter_calculated_threshold_value] > 20 THEN \u0027[WARNING: Greater than 20 Lazy Writes per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page life expectancy\u0027 AND [counter_calculated_threshold_value] < 300 THEN \u0027[WARNING: Less than 300 seconds of Page Life Expectancy]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page life expectancy\u0027 AND [counter_calculated_threshold_value] < 700 THEN \u0027[WARNING: Less than 700 seconds of Page Life Expectancy]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page lookups/sec\u0027 AND [counter_calculated_threshold_value] > 1 THEN \u0027[WARNING: A ratio of more than 1 page lookup for every 100 batch requests]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page reads/sec\u0027 AND [counter_calculated_threshold_value] > 90 THEN \u0027[WARNING: Greater than 90 page reads per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page writes/sec\u0027 AND [counter_calculated_threshold_value] > 30 THEN \u0027[WARNING: Page writes are more than 30 percent of page reads per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Page writes/sec\u0027 AND [counter_value] > 90 THEN \u0027[WARNING: Greater than 90 page writes per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Readahead pages/sec\u0027 AND [counter_calculated_threshold_value] > 20 THEN \u0027[WARNING: More than 20 percent of page reads per second]\u0027\r\n", "\t\t\tWHEN [counter_name] IN (\u0027Log Flush Wait Time\u0027,\u0027Log Flush Waits/sec\u0027,\u0027Lock Waits/sec\u0027,\u0027Number of Deadlocks/sec\u0027) AND [counter_calculated_threshold_value] > 0 THEN \u0027[WARNING: Greater than 0]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Average Latch Wait Time (ms)\u0027 AND [counter_calculated_threshold_value] > 10 THEN \u0027[WARNING: Latch wait is more than 10 milliseconds on average]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Total Latch Wait Time (ms)\u0027 AND [counter_calculated_threshold_value] > 500 THEN \u0027[WARNING: Total latch wait time is above 500 ms per each second on average]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Total Latch Wait Time (ms)\u0027 AND [counter_calculated_threshold_value] > 750 THEN \u0027[WARNING: Total latch wait time is above 750 ms per each second on average]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Lock Requests/sec\u0027 AND [counter_calculated_threshold_value] > 500 THEN \u0027[WARNING: A ratio of more than 500 lock requests per batch request]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Target Server Memory (KB)\u0027 AND [counter_calculated_threshold_value] > 500 THEN \u0027[WARNING: Target Server Memory is more than 500MBs above Total Server Memory]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027Batch Requests/sec\u0027 AND [counter_calculated_threshold_value] > 1000 THEN \u0027[WARNING: Greater than 1000 batch requests per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027SQL Compilations/sec\u0027 AND [counter_calculated_threshold_value] > 10 THEN \u0027[WARNING: A ratio of more than 1 SQL Compilation for every 10 Batch Requests per second]\u0027\r\n", "\t\t\tWHEN [counter_name] = \u0027SQL Re-Compilations/sec\u0027 AND [counter_calculated_threshold_value] > 10 THEN \u0027[WARNING: A ratio of more than 1 SQL Re-Compilation for every 10 SQL Compilations]\u0027\r\n", "\t\t\tWHEN [counter_calculated_threshold_value] IS NULL THEN NULL\r\n", "\t\tELSE \u0027[OK]\u0027 END AS [Deviation]\r\n", "\t\tFROM ctectr\r\n", "\t\tORDER BY [counter_family],[counter_name],[counter_instance];\r\n", "\t\tIF @sqlmajorver >= 11\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Perf_Counters\u0027 AS [Information], [counter_name] AS Counter_name, \"CPU Time:Total(ms)\", \"CPU Time:Requests\", \"Elapsed Time:Total(ms)\", \"Elapsed Time:Requests\"\r\n", "\t\t\tFROM (SELECT [counter_name], [instance_name], [cntr_value]\r\n", "\t\t\t\tFROM #tblPerfCount\r\n", "\t\t\t\tWHERE [object_name] LIKE \u0027%Batch Resp Statistics%\u0027) AS pc\r\n", "\t\tPIVOT(AVG([cntr_value]) FOR [instance_name]\r\n", "\t\tIN (\"CPU Time:Total(ms)\", \"CPU Time:Requests\", \"Elapsed Time:Total(ms)\", \"Elapsed Time:Requests\")\r\n", "\t\t) AS Pvt;\r\n", "\t\tEND\r\n", "\t;\r\n", "\t\tWITH\r\n", "\t\t\tcteWaits1 (wait_type, wait_time_ms, signal_wait_time_ms, resource_wait_time_ms)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT wait_type, wait_time_ms, signal_wait_time_ms, resource_wait_time_ms\r\n", "\t\t\t\tFROM #tblWaits\r\n", "\t\t\t\tWHERE [retrieval_time] = @minctr\r\n", "\t\t\t),\r\n", "\t\t\tcteWaits2 (wait_type, wait_time_ms, signal_wait_time_ms, resource_wait_time_ms)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT wait_type, wait_time_ms, signal_wait_time_ms, resource_wait_time_ms\r\n", "\t\t\t\tFROM #tblWaits\r\n", "\t\t\t\tWHERE [retrieval_time] = @maxctr\r\n", "\t\t\t)\r\n", "\t\tINSERT INTO #tblFinalWaits\r\n", "\t\tSELECT DISTINCT t1.wait_type, (t2.wait_time_ms-t1.wait_time_ms) / 1000. AS wait_time_s,\r\n", "\t\t\t(t2.signal_wait_time_ms-t1.signal_wait_time_ms) / 1000. AS signal_wait_time_s,\r\n", "\t\t\t((t2.wait_time_ms-t2.signal_wait_time_ms)-(t1.wait_time_ms-t1.signal_wait_time_ms)) / 1000. AS resource_wait_time_s,\r\n", "\t\t\t100.0 * (t2.wait_time_ms-t1.wait_time_ms) / SUM(t2.wait_time_ms-t1.wait_time_ms) OVER() AS pct,\r\n", "\t\t\tROW_NUMBER() OVER(ORDER BY (t2.wait_time_ms-t1.wait_time_ms) DESC) AS rn,\r\n", "\t\t\tSUM(t2.signal_wait_time_ms-t1.signal_wait_time_ms) * 1.0 / SUM(t2.wait_time_ms-t1.wait_time_ms) * 100 AS signal_wait_pct,\r\n", "\t\t\t(SUM(t2.wait_time_ms-t2.signal_wait_time_ms)-SUM(t1.wait_time_ms-t1.signal_wait_time_ms)) * 1.0 / (SUM(t2.wait_time_ms)-SUM(t1.wait_time_ms)) * 100 AS resource_wait_pct\r\n", "\t\tFROM cteWaits1 t1 INNER JOIN cteWaits2 t2 ON t1.wait_type = t2.wait_type\r\n", "\t\tGROUP BY t1.wait_type, t1.wait_time_ms, t1.signal_wait_time_ms, t1.resource_wait_time_ms, t2.wait_time_ms, t2.signal_wait_time_ms, t2.resource_wait_time_ms\r\n", "\t\tHAVING (t2.wait_time_ms-t1.wait_time_ms) > 0\r\n", "\t\tORDER BY wait_time_s DESC;\r\n", "\t-- SOS_SCHEDULER_YIELD = Might indicate CPU pressure if very high overall percentage. Check yielding conditions in http://technet.microsoft.com/library/cc917684.aspx\r\n", "\t-- THREADPOOL = Look for high blocking or contention problems with workers. This will not show up in sys.dm_exec_requests;\r\n", "\t-- LATCH = indicates contention for access to some non-page structures. ACCESS_METHODS_DATASET_PARENT, ACCESS_METHODS_SCAN_RANGE_GENERATOR or NESTING_TRANSACTION_FULL latches indicate parallelism issues;\r\n", "\t-- PAGELATCH = indicates contention for access to in-memory copies of pages, like PFS, SGAM and GAM; \r\n", "\t-- PAGELATCH_UP = Does the filegroup have enough files? Contention in PFS?\r\n", "\t-- PAGELATCH_EX = Contention while doing many UPDATE statements against small tables? \r\n", "\t-- PAGELATCH_EX = Many concurrent INSERT statements into a table that has an index on an IDENTITY or NEWSEQUENTIALID column? -> https://techcommunity.microsoft.com/t5/SQL-Server/PAGELATCH-EX-waits-and-heavy-inserts/ba-p/384289\r\n", "\t-- PAGEIOLATCH = indicates IO problems, or BP pressure.\r\n", "\t-- PREEMPTIVE_OS_WRITEFILEGATHERER (2008+) = usually autogrow scenarios, usually together with WRITELOG;\r\n", "\t-- IO_COMPLETION = usually TempDB spilling; \r\n", "\t-- ASYNC_IO_COMPLETION = usually when not using IFI, or waiting on backups.\r\n", "\t-- DISKIO_SUSPEND = High wait times here indicate the SNAPSHOT BACKUP may be taking longer than expected. Typically the delay is within the VDI application perform the snapshot backup;\r\n", "\t-- BACKUPIO = check for slow backup media slow, like Tapes or Disks;\r\n", "\t-- BACKUPBUFFER = usually when backing up to Tape;\r\n", "\t-- Check sys.dm_os_waiting_tasks for Exchange wait types in https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-os-waiting-tasks-transact-sql\r\n", "\t-- Wait Resource e_waitPipeNewRow in CXPACKET waits Producer waiting on consumer for a packet to fill;\r\n", "\t-- Wait Resource e_waitPipeGetRow in CXPACKET waits Consumer waiting on producer to fill a packet;\r\n", "\t-- CXPACKET = if OLTP, check for parallelism issues if above 20 pct. If combined with a high number of PAGEIOLATCH_XX waits, it could be large parallel table scans going on because of incorrect non-clustered indexes, or out-of-date statistics causing a bad query plan;\r\n", "\t-- HT* = batch mode syncpoint waits, probably large parallel table scans; \r\n", "\t-- WRITELOG = log management system waiting for a log flush to disk. Examine the I/O latency for the log file\r\n", "\t-- CMEMTHREAD = indicates that the rate of insertion of entries into the plan cache is very high and there is contention -> https://techcommunity.microsoft.com/t5/SQL-Server-Support/How-It-Works-CMemThread-and-Debugging-Them/ba-p/317488\r\n", "\t-- SOS_RESERVEDMEMBLOCKLIST = look for procedures with a large number of parameters, or queries with a long list of expression values specified in an IN clause, which would require multi-page allocations\r\n", "\t-- RESOURCE_SEMAPHORE_SMALL_QUERY or RESOURCE_SEMAPHORE = queries are waiting for execution memory. Look for plans with excessive hashing or sorts.\r\n", "\t-- RESOURCE_SEMAPHORE_QUERY_COMPILE = usually high compilation or recompilation scenario (higher ratio of prepared plans vs. compiled plans). On x64 usually memory hungry queries and compiles. On x86 perhaps short on VAS. -> http://technet.microsoft.com/library/cc293620.aspx\r\n", "\t-- DBMIRROR_DBM_MUTEX = indicates contention for the send buffer that database mirroring shares between all the mirroring sessions. \r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Waits_Last_\u0027 + CONVERT(VARCHAR(3), @duration) + \u0027s\u0027 AS [Information], W1.wait_type,\r\n", "\t\t\tCAST(W1.wait_time_s AS DECIMAL(14, 2)) AS wait_time_s,\r\n", "\t\t\tCAST(W1.signal_wait_time_s AS DECIMAL(14, 2)) AS signal_wait_time_s,\r\n", "\t\t\tCAST(W1.resource_wait_time_s AS DECIMAL(14, 2)) AS resource_wait_time_s,\r\n", "\t\t\tCAST(W1.pct AS DECIMAL(14, 2)) AS pct,\r\n", "\t\t\tCAST(SUM(W2.pct) AS DECIMAL(14, 2)) AS overall_running_pct,\r\n", "\t\t\tCAST(W1.signal_wait_pct AS DECIMAL(14, 2)) AS signal_wait_pct,\r\n", "\t\t\tCAST(W1.resource_wait_pct AS DECIMAL(14, 2)) AS resource_wait_pct,\r\n", "\t\t\tCASE WHEN W1.wait_type = N\u0027SOS_SCHEDULER_YIELD\u0027 THEN N\u0027CPU\u0027 \r\n", "\t\t\tWHEN W1.wait_type = N\u0027THREADPOOL\u0027 THEN \u0027CPU - Unavailable Worker Threads\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027LCK_%\u0027 OR W1.wait_type = N\u0027LOCK\u0027 THEN N\u0027Lock\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027LATCH_%\u0027 THEN N\u0027Latch\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PAGELATCH_%\u0027 THEN N\u0027Buffer Latch\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PAGEIOLATCH_%\u0027 THEN N\u0027Buffer IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027HADR_SYNC_COMMIT\u0027 THEN N\u0027Always On - Secondary Synch\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027HADR_%\u0027 OR W1.wait_type LIKE N\u0027PWAIT_HADR_%\u0027 THEN N\u0027Always On\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027FFT_%\u0027 THEN N\u0027FileTable\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_%\u0027 OR W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_QUERY_COMPILE\u0027 THEN N\u0027Memory - Compilation\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027UTIL_PAGE_ALLOC\u0027, N\u0027SOS_VIRTUALMEMORY_LOW\u0027, N\u0027SOS_RESERVEDMEMBLOCKLIST\u0027, N\u0027RESOURCE_SEMAPHORE\u0027, N\u0027CMEMTHREAD\u0027, N\u0027CMEMPARTITIONED\u0027, N\u0027EE_PMOLOCK\u0027, N\u0027MEMORY_ALLOCATION_EXT\u0027, N\u0027RESERVED_MEMORY_ALLOCATION_EXT\u0027, N\u0027MEMORY_GRANT_UPDATE\u0027) THEN N\u0027Memory\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027CLR%\u0027 OR W1.wait_type LIKE N\u0027SQLCLR%\u0027 THEN N\u0027SQL CLR\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027DBMIRROR%\u0027 OR W1.wait_type = N\u0027MIRROR_SEND_MESSAGE\u0027 THEN N\u0027Mirroring\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027XACT%\u0027 or W1.wait_type LIKE N\u0027DTC%\u0027 or W1.wait_type LIKE N\u0027TRAN_MARKLATCH_%\u0027 or W1.wait_type LIKE N\u0027MSQL_XACT_%\u0027 or W1.wait_type = N\u0027TRANSACTION_MUTEX\u0027 THEN N\u0027Transaction\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PREEMPTIVE_%\u0027 THEN N\u0027External APIs or XPs\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027BROKER_%\u0027 AND W1.wait_type <> N\u0027BROKER_RECEIVE_WAITFOR\u0027 THEN N\u0027Service Broker\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027LOGMGR\u0027, N\u0027LOGBUFFER\u0027, N\u0027LOGMGR_RESERVE_APPEND\u0027, N\u0027LOGMGR_FLUSH\u0027, N\u0027LOGMGR_PMM_LOG\u0027, N\u0027CHKPT\u0027, N\u0027WRITELOG\u0027) THEN N\u0027Tran Log IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027ASYNC_NETWORK_IO\u0027, N\u0027NET_WAITFOR_PACKET\u0027, N\u0027PROXY_NETWORK_IO\u0027, N\u0027EXTERNAL_SCRIPT_NETWORK_IO\u0027) THEN N\u0027Network IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027CXPACKET\u0027, N\u0027EXCHANGE\u0027, N\u0027CXCONSUMER\u0027, N\u0027HTBUILD\u0027, N\u0027HTDELETE\u0027, N\u0027HTMEMO\u0027, N\u0027HTREINIT\u0027, N\u0027HTREPARTITION\u0027) THEN N\u0027CPU - Parallelism\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027WAITFOR\u0027, N\u0027WAIT_FOR_RESULTS\u0027, N\u0027BROKER_RECEIVE_WAITFOR\u0027) THEN N\u0027User Wait\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027TRACEWRITE\u0027, N\u0027SQLTRACE_LOCK\u0027, N\u0027SQLTRACE_FILE_BUFFER\u0027, N\u0027SQLTRACE_FILE_WRITE_IO_COMPLETION\u0027, N\u0027SQLTRACE_FILE_READ_IO_COMPLETION\u0027, N\u0027SQLTRACE_PENDING_BUFFER_WRITERS\u0027, N\u0027SQLTRACE_SHUTDOWN\u0027, N\u0027QUERY_TRACEOUT\u0027, N\u0027TRACE_EVTNOTIF\u0027) THEN N\u0027Tracing\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027FT_%\u0027 OR W1.wait_type IN (N\u0027FULLTEXT GATHERER\u0027, N\u0027MSSEARCH\u0027, N\u0027PWAIT_RESOURCE_SEMAPHORE_FT_PARALLEL_QUERY_SYNC\u0027) THEN N\u0027Full Text Search\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027ASYNC_IO_COMPLETION\u0027, N\u0027IO_COMPLETION\u0027, N\u0027WRITE_COMPLETION\u0027, N\u0027IO_QUEUE_LIMIT\u0027, /*N\u0027HADR_FILESTREAM_IOMGR_IOCOMPLETION\u0027,*/ N\u0027IO_RETRY\u0027) THEN N\u0027Other Disk IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027BACKUPIO\u0027, N\u0027BACKUPBUFFER\u0027) THEN \u0027Backup IO\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027SE_REPL_%\u0027 or W1.wait_type LIKE N\u0027REPL_%\u0027 or W1.wait_type IN (N\u0027REPLICA_WRITES\u0027, N\u0027FCB_REPLICA_WRITE\u0027, N\u0027FCB_REPLICA_READ\u0027, N\u0027PWAIT_HADRSIM\u0027) THEN N\u0027Replication\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027LOG_RATE_GOVERNOR\u0027, N\u0027POOL_LOG_RATE_GOVERNOR\u0027, N\u0027HADR_THROTTLE_LOG_RATE_GOVERNOR\u0027, N\u0027INSTANCE_LOG_RATE_GOVERNOR\u0027) THEN N\u0027Log Rate Governor\u0027 \r\n", "\t\t\tWHEN W1.wait_type = N\u0027REPLICA_WRITE\u0027 THEN \u0027Snapshots\u0027\r\n", "\t\t\tWHEN W1.wait_type = N\u0027WAIT_XTP_OFFLINE_CKPT_LOG_IO\u0027 OR W1.wait_type = N\u0027WAIT_XTP_CKPT_CLOSE\u0027 THEN \u0027In-Memory OLTP Logging\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027QDS%\u0027 THEN N\u0027Query Store\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027XTP%\u0027 OR W1.wait_type LIKE N\u0027WAIT_XTP%\u0027 THEN N\u0027In-Memory OLTP\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PARALLEL_REDO%\u0027 THEN N\u0027Parallel Redo\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027COLUMNSTORE%\u0027 THEN N\u0027Columnstore\u0027\r\n", "\t\tELSE N\u0027Other\u0027 END AS \u0027wait_category\u0027\r\n", "\t\tFROM #tblFinalWaits AS W1 INNER JOIN #tblFinalWaits AS W2 ON W2.rn <= W1.rn\r\n", "\t\tGROUP BY W1.rn, W1.wait_type, CAST(W1.wait_time_s AS DECIMAL(14, 2)), CAST(W1.pct AS DECIMAL(14, 2)), CAST(W1.signal_wait_time_s AS DECIMAL(14, 2)), CAST(W1.resource_wait_time_s AS DECIMAL(14, 2)), CAST(W1.signal_wait_pct AS DECIMAL(14, 2)), CAST(W1.resource_wait_pct AS DECIMAL(14, 2))\r\n", "\t\tHAVING CAST(W1.wait_time_s as DECIMAL(14, 2)) >= 0.01 AND (SUM(W2.pct)-CAST(W1.pct AS DECIMAL(14, 2))) < 100\r\n", "\t-- percentage threshold\r\n", "\t\tORDER BY W1.rn;\r\n", "\t\t;WITH\r\n", "\t\t\tWaits\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT wait_type, wait_time_ms / 1000. AS wait_time_s,\r\n", "\t\t\t\t\tsignal_wait_time_ms / 1000. AS signal_wait_time_s,\r\n", "\t\t\t\t\t(wait_time_ms-signal_wait_time_ms) / 1000. AS resource_wait_time_s,\r\n", "\t\t\t\t\tSUM(signal_wait_time_ms) * 1.0 / SUM(wait_time_ms) * 100 AS signal_wait_pct,\r\n", "\t\t\t\t\tSUM(wait_time_ms-signal_wait_time_ms) * 1.0 / SUM(wait_time_ms) * 100 AS resource_wait_pct,\r\n", "\t\t\t\t\t100.0 * wait_time_ms / SUM(wait_time_ms) OVER() AS pct,\r\n", "\t\t\t\t\tROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn\r\n", "\t\t\t\tFROM sys.dm_os_wait_stats\r\n", "\t\t\t\tWHERE wait_type NOT IN (\u0027RESOURCE_QUEUE\u0027, \u0027SQLTRACE_INCREMENTAL_FLUSH_SLEEP\u0027, \r\n", "\t\u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027,\r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027LOGMGR_QUEUE\u0027,\u0027CHECKPOINT_QUEUE\u0027,\u0027REQUEST_FOR_DEADLOCK_SEARCH\u0027,\u0027XE_TIMER_EVENT\u0027,\r\n", "\t\u0027BROKER_TASK_STOP\u0027,\u0027CLR_MANUAL_EVENT\u0027, \u0027CLR_AUTO_EVENT\u0027,\u0027DISPATCHER_QUEUE_SEMAPHORE\u0027, \u0027FT_IFTS_SCHEDULER_IDLE_WAIT\u0027,\u0027BROKER_TO_FLUSH\u0027,\r\n", "\t\u0027XE_DISPATCHER_WAIT\u0027, \u0027XE_DISPATCHER_JOIN\u0027, \u0027MSQL_XP\u0027, \u0027WAIT_FOR_RESULTS\u0027, \u0027CLR_SEMAPHORE\u0027, \u0027LAZYWRITER_SLEEP\u0027, \u0027SLEEP_TASK\u0027,\r\n", "\t\u0027SLEEP_SYSTEMTASK\u0027, \u0027SQLTRACE_BUFFER_FLUSH\u0027, \u0027WAITFOR\u0027, \u0027BROKER_EVENTHANDLER\u0027, \u0027TRACEWRITE\u0027, \u0027FT_IFTSHC_MUTEX\u0027, \u0027BROKER_RECEIVE_WAITFOR\u0027, \r\n", "\t\u0027ONDEMAND_TASK_QUEUE\u0027, \u0027DBMIRROR_EVENTS_QUEUE\u0027, \u0027DBMIRRORING_CMD\u0027, \u0027BROKER_TRANSMITTER\u0027, \u0027SQLTRACE_WAIT_ENTRIES\u0027, \u0027SLEEP_BPOOL_FLUSH\u0027, \u0027SQLTRACE_LOCK\u0027,\r\n", "\t\u0027DIRTY_PAGE_POLL\u0027, \u0027HADR_FILESTREAM_IOMGR_IOCOMPLETION\u0027, \u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027, \u0027QDS_PERSIST_TASK_MAIN_LOOP_SLEEP\u0027, \r\n", "\t\u0027QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP\u0027, \u0027WAIT_XTP_OFFLINE_CKPT_NEW_LOG\u0027, \u0027SOSHOST_SLEEP\u0027, \u0027SP_PREEMPTIVE_SERVER_DIAGNOSTICS_SLEEP\u0027)\r\n", "\t\t\t\t\tAND wait_type NOT LIKE N\u0027SLEEP_%\u0027\r\n", "\t\t\t\tGROUP BY wait_type, wait_time_ms, signal_wait_time_ms\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Cumulative_Waits\u0027 AS [Information], W1.wait_type,\r\n", "\t\t\tCAST(W1.wait_time_s AS DECIMAL(14, 2)) AS wait_time_s,\r\n", "\t\t\tCAST(W1.signal_wait_time_s AS DECIMAL(14, 2)) AS signal_wait_time_s,\r\n", "\t\t\tCAST(W1.resource_wait_time_s AS DECIMAL(14, 2)) AS resource_wait_time_s,\r\n", "\t\t\tCAST(W1.pct AS DECIMAL(14, 2)) AS pct,\r\n", "\t\t\tCAST(SUM(W2.pct) AS DECIMAL(14, 2)) AS overall_running_pct,\r\n", "\t\t\tCAST(W1.signal_wait_pct AS DECIMAL(14, 2)) AS signal_wait_pct,\r\n", "\t\t\tCAST(W1.resource_wait_pct AS DECIMAL(14, 2)) AS resource_wait_pct,\r\n", "\t\t\tCASE WHEN W1.wait_type = N\u0027SOS_SCHEDULER_YIELD\u0027 THEN N\u0027CPU\u0027 \r\n", "\t\t\tWHEN W1.wait_type = N\u0027THREADPOOL\u0027 THEN \u0027CPU - Unavailable Worker Threads\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027LCK_%\u0027 OR W1.wait_type = N\u0027LOCK\u0027 THEN N\u0027Lock\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027LATCH_%\u0027 THEN N\u0027Latch\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PAGELATCH_%\u0027 THEN N\u0027Buffer Latch\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PAGEIOLATCH_%\u0027 THEN N\u0027Buffer IO\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027HADR_SYNC_COMMIT\u0027 THEN N\u0027Always On - Secondary Synch\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027HADR_%\u0027 OR W1.wait_type LIKE N\u0027PWAIT_HADR_%\u0027 THEN N\u0027Always On\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027FFT_%\u0027 THEN N\u0027FileTable\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_%\u0027 OR W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_QUERY_COMPILE\u0027 THEN N\u0027Memory - Compilation\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027UTIL_PAGE_ALLOC\u0027, N\u0027SOS_VIRTUALMEMORY_LOW\u0027, N\u0027SOS_RESERVEDMEMBLOCKLIST\u0027, N\u0027RESOURCE_SEMAPHORE\u0027, N\u0027CMEMTHREAD\u0027, N\u0027CMEMPARTITIONED\u0027, N\u0027EE_PMOLOCK\u0027, N\u0027MEMORY_ALLOCATION_EXT\u0027, N\u0027RESERVED_MEMORY_ALLOCATION_EXT\u0027, N\u0027MEMORY_GRANT_UPDATE\u0027) THEN N\u0027Memory\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027CLR%\u0027 OR W1.wait_type LIKE N\u0027SQLCLR%\u0027 THEN N\u0027SQL CLR\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027DBMIRROR%\u0027 OR W1.wait_type = N\u0027MIRROR_SEND_MESSAGE\u0027 THEN N\u0027Mirroring\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027XACT%\u0027 or W1.wait_type LIKE N\u0027DTC%\u0027 or W1.wait_type LIKE N\u0027TRAN_MARKLATCH_%\u0027 or W1.wait_type LIKE N\u0027MSQL_XACT_%\u0027 or W1.wait_type = N\u0027TRANSACTION_MUTEX\u0027 THEN N\u0027Transaction\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PREEMPTIVE_%\u0027 THEN N\u0027External APIs or XPs\u0027 -- Used to indicate a worker is running code that is not under the SQLOS Scheduling;\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027BROKER_%\u0027 AND W1.wait_type <> N\u0027BROKER_RECEIVE_WAITFOR\u0027 THEN N\u0027Service Broker\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027LOGMGR\u0027, N\u0027LOGBUFFER\u0027, N\u0027LOGMGR_RESERVE_APPEND\u0027, N\u0027LOGMGR_FLUSH\u0027, N\u0027LOGMGR_PMM_LOG\u0027, N\u0027CHKPT\u0027, N\u0027WRITELOG\u0027) THEN N\u0027Tran Log IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027ASYNC_NETWORK_IO\u0027, N\u0027NET_WAITFOR_PACKET\u0027, N\u0027PROXY_NETWORK_IO\u0027, N\u0027EXTERNAL_SCRIPT_NETWORK_IO\u0027) THEN N\u0027Network IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027CXPACKET\u0027, N\u0027EXCHANGE\u0027, N\u0027CXCONSUMER\u0027) THEN N\u0027CPU - Parallelism\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027WAITFOR\u0027, N\u0027WAIT_FOR_RESULTS\u0027, N\u0027BROKER_RECEIVE_WAITFOR\u0027) THEN N\u0027User Wait\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027TRACEWRITE\u0027, N\u0027SQLTRACE_LOCK\u0027, N\u0027SQLTRACE_FILE_BUFFER\u0027, N\u0027SQLTRACE_FILE_WRITE_IO_COMPLETION\u0027, N\u0027SQLTRACE_FILE_READ_IO_COMPLETION\u0027, N\u0027SQLTRACE_PENDING_BUFFER_WRITERS\u0027, N\u0027SQLTRACE_SHUTDOWN\u0027, N\u0027QUERY_TRACEOUT\u0027, N\u0027TRACE_EVTNOTIF\u0027) THEN N\u0027Tracing\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027FT_%\u0027 OR W1.wait_type IN (N\u0027FULLTEXT GATHERER\u0027, N\u0027MSSEARCH\u0027, N\u0027PWAIT_RESOURCE_SEMAPHORE_FT_PARALLEL_QUERY_SYNC\u0027) THEN N\u0027Full Text Search\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027ASYNC_IO_COMPLETION\u0027, N\u0027IO_COMPLETION\u0027, N\u0027WRITE_COMPLETION\u0027, N\u0027IO_QUEUE_LIMIT\u0027, /*N\u0027HADR_FILESTREAM_IOMGR_IOCOMPLETION\u0027,*/ N\u0027IO_RETRY\u0027) THEN N\u0027Other Disk IO\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN(N\u0027BACKUPIO\u0027, N\u0027BACKUPBUFFER\u0027) THEN \u0027Backup IO\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027CXPACKET\u0027, N\u0027EXCHANGE\u0027, N\u0027CXCONSUMER\u0027) THEN N\u0027CPU - Parallelism\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027LOGMGR\u0027, N\u0027LOGBUFFER\u0027, N\u0027LOGMGR_RESERVE_APPEND\u0027, N\u0027LOGMGR_FLUSH\u0027, N\u0027WRITELOG\u0027) THEN N\u0027Logging\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027NET_WAITFOR_PACKET\u0027,N\u0027NETWORK_IO\u0027) THEN N\u0027Network IO\u0027\r\n", "\t\t\tWHEN W1.wait_type = N\u0027ASYNC_NETWORK_IO\u0027 THEN N\u0027Client Network IO\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027UTIL_PAGE_ALLOC\u0027,N\u0027SOS_VIRTUALMEMORY_LOW\u0027,N\u0027CMEMTHREAD\u0027, N\u0027SOS_RESERVEDMEMBLOCKLIST\u0027) THEN N\u0027Memory\u0027 \r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027RESOURCE_SEMAPHORE_SMALL_QUERY\u0027, N\u0027RESOURCE_SEMAPHORE\u0027) THEN N\u0027Memory - Hash or Sort\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_%\u0027 OR W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_QUERY_COMPILE\u0027 THEN N\u0027Memory - Compilation\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027CLR_%\u0027 OR W1.wait_type LIKE N\u0027SQLCLR%\u0027 THEN N\u0027CLR\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027DBMIRROR%\u0027 OR W1.wait_type = N\u0027MIRROR_SEND_MESSAGE\u0027 THEN N\u0027Mirroring\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_%\u0027 OR W1.wait_type LIKE N\u0027RESOURCE_SEMAPHORE_QUERY_COMPILE\u0027 THEN N\u0027Compilation\u0027 \r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027XACT%\u0027 OR W1.wait_type LIKE N\u0027DTC_%\u0027 OR W1.wait_type LIKE N\u0027TRAN_MARKLATCH_%\u0027 OR W1.wait_type LIKE N\u0027MSQL_XACT_%\u0027 OR W1.wait_type = N\u0027TRANSACTION_MUTEX\u0027 THEN N\u0027Transaction\u0027\r\n", "\t\t\tWHEN W1.wait_type IN (N\u0027LOG_RATE_GOVERNOR\u0027, N\u0027POOL_LOG_RATE_GOVERNOR\u0027, N\u0027HADR_THROTTLE_LOG_RATE_GOVERNOR\u0027, N\u0027INSTANCE_LOG_RATE_GOVERNOR\u0027) THEN N\u0027Log Rate Governor\u0027 \r\n", "\t\t\tWHEN W1.wait_type = N\u0027REPLICA_WRITE\u0027 THEN \u0027Snapshots\u0027\r\n", "\t\t\tWHEN W1.wait_type = N\u0027WAIT_XTP_OFFLINE_CKPT_LOG_IO\u0027 OR W1.wait_type = N\u0027WAIT_XTP_CKPT_CLOSE\u0027 THEN \u0027In-Memory OLTP Logging\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027QDS%\u0027 THEN N\u0027Query Store\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027XTP%\u0027 OR W1.wait_type LIKE N\u0027WAIT_XTP%\u0027 THEN N\u0027In-Memory OLTP\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027PARALLEL_REDO%\u0027 THEN N\u0027Parallel Redo\u0027\r\n", "\t\t\tWHEN W1.wait_type LIKE N\u0027COLUMNSTORE%\u0027 THEN N\u0027Columnstore\u0027\r\n", "\t\tELSE N\u0027Other\u0027 END AS \u0027wait_category\u0027\r\n", "\t\tFROM Waits AS W1 INNER JOIN Waits AS W2 ON W2.rn <= W1.rn\r\n", "\t\tGROUP BY W1.rn, W1.wait_type, CAST(W1.wait_time_s AS DECIMAL(14, 2)), CAST(W1.pct AS DECIMAL(14, 2)), CAST(W1.signal_wait_time_s AS DECIMAL(14, 2)), CAST(W1.resource_wait_time_s AS DECIMAL(14, 2)), CAST(W1.signal_wait_pct AS DECIMAL(14, 2)), CAST(W1.resource_wait_pct AS DECIMAL(14, 2))\r\n", "\t\tHAVING CAST(W1.wait_time_s as DECIMAL(14, 2)) >= 0.01 AND (SUM(W2.pct)-CAST(W1.pct AS DECIMAL(14, 2))) < 100\r\n", "\t-- percentage threshold\r\n", "\t\tORDER BY W1.rn;\r\n", "\t-- ACCESS_METHODS_HOBT_VIRTUAL_ROOT = This latch is used to access the metadata for an index that contains the page ID of the index\u0027s root page. Contention on this latch can occur when a B-tree root page split occurs (requiring the latch in EX mode) and threads wanting to navigate down the B-tree (requiring the latch in SH mode) have to wait. This could be from very fast population of a small index using many concurrent connections, with or without page splits from random key values causing cascading page splits (from leaf to root).\r\n", "\t-- ACCESS_METHODS_HOBT_COUNT = This latch is used to flush out page and row count deltas for a HoBt (Heap-or-B-tree) to the Storage Engine metadata tables. Contention would indicate *lots* of small, concurrent DML operations on a single table. \r\n", "\t-- ACCESS_METHODS_DATASET_PARENT and ACCESS_METHODS_SCAN_RANGE_GENERATOR = These two latches are used during parallel scans to give each thread a range of page IDs to scan. The LATCH_XX waits for these latches will typically appear with CXPACKET waits and PAGEIOLATCH_XX waits (if the data being scanned is not memory-resident). Use normal parallelism troubleshooting methods to investigate further (e.g. is the parallelism warranted? maybe increase \u0027cost threshold for parallelism\u0027, lower MAXDOP, use a MAXDOP hint, use Resource Governor to limit DOP using a workload group with a MAX_DOP limit. Did a plan change from index seeks to parallel table scans because a tipping point was reached or a plan recompiled with an atypical SP parameter or poor statistics? Do NOT knee-jerk and set server MAXDOP to 1 – that\u0027s some of the worst advice I see on the Internet.);\r\n", "\t-- NESTING_TRANSACTION_FULL = This latch, along with NESTING_TRANSACTION_READONLY, is used to control access to transaction description structures (called an XDES) for parallel nested transactions. The _FULL is for a transaction that\u0027s \u0027active\u0027, i.e. it\u0027s changed the database (usually for an index build/rebuild), and that makes the _READONLY description obvious. A query that involves a parallel operator must start a sub-transaction for each parallel thread that is used – these transactions are sub-transactions of the parallel nested transaction. For contention on these, I\u0027d investigate unwanted parallelism but I don\u0027t have a definite \"it\u0027s usually this problem\". Also check out the comments for some info about these also sometimes being a problem when RCSI is used.\r\n", "\t-- LOG_MANAGER = you see this latch it is almost certainly because a transaction log is growing because it could not clear/truncate for some reason. Find the database where the log is growing and then figure out what\u0027s preventing log clearing using sys.databases.\r\n", "\t-- DBCC_MULTIOBJECT_SCANNER = This latch appears on Enterprise Edition when DBCC CHECK_ commands are allowed to run in parallel. It is used by threads to request the next data file page to process. Late last year this was identified as a major contention point inside DBCC CHECK* and there was work done to reduce the contention and make DBCC CHECK* run faster.\r\n", "\t-- https://techcommunity.microsoft.com/t5/SQL-Server-Support/A-faster-CHECKDB-8211-Part-II/ba-p/316882\r\n", "\t-- FGCB_ADD_REMOVE = FGCB stands for File Group Control Block. This latch is required whenever a file is added or dropped from the filegroup, whenever a file is grown (manually or automatically), when recalculating proportional-fill weightings, and when cycling through the files in the filegroup as part of round-robin allocation. If you\u0027re seeing this, the most common cause is that there\u0027s a lot of file auto-growth happening. It could also be from a filegroup with lots of file (e.g. the primary filegroup in tempdb) where there are thousands of concurrent connections doing allocations. The proportional-fill weightings are recalculated every 8192 allocations, so there\u0027s the possibility of a slowdown with frequent recalculations over many files.\r\n", "\t\t;WITH\r\n", "\t\t\tcteLatches1 (latch_class, wait_time_ms, waiting_requests_count)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT latch_class, wait_time_ms, waiting_requests_count\r\n", "\t\t\t\tFROM #tblLatches\r\n", "\t\t\t\tWHERE [retrieval_time] = @minctr\r\n", "\t\t\t),\r\n", "\t\t\tcteLatches2 (latch_class, wait_time_ms, waiting_requests_count)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT latch_class, wait_time_ms, waiting_requests_count\r\n", "\t\t\t\tFROM #tblLatches\r\n", "\t\t\t\tWHERE [retrieval_time] = @maxctr\r\n", "\t\t\t)\r\n", "\t\tINSERT INTO #tblFinalLatches\r\n", "\t\tSELECT DISTINCT t1.latch_class,\r\n", "\t\t\tCAST((t2.wait_time_ms-t1.wait_time_ms) / 1000.0 AS DECIMAL(14, 2)) AS wait_time_s,\r\n", "\t\t\t(t2.waiting_requests_count-t1.waiting_requests_count) AS waiting_requests_count,\r\n", "\t\t\t100.0 * (t2.wait_time_ms-t1.wait_time_ms) / SUM(t2.wait_time_ms-t1.wait_time_ms) OVER() AS pct,\r\n", "\t\t\tROW_NUMBER() OVER(ORDER BY t1.wait_time_ms DESC) AS rn\r\n", "\t\tFROM cteLatches1 t1 INNER JOIN cteLatches2 t2 ON t1.latch_class = t2.latch_class\r\n", "\t\tGROUP BY t1.latch_class, t1.wait_time_ms, t2.wait_time_ms, t1.waiting_requests_count, t2.waiting_requests_count\r\n", "\t\tHAVING (t2.wait_time_ms-t1.wait_time_ms) > 0\r\n", "\t\tORDER BY wait_time_s DESC;\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Latches_Last_\u0027 + CONVERT(VARCHAR(3), @duration) + \u0027s\u0027 AS [Information], W1.latch_class,\r\n", "\t\t\tW1.wait_time_s,\r\n", "\t\t\tW1.waiting_requests_count,\r\n", "\t\t\tCAST(W1.pct AS DECIMAL(14, 2)) AS pct,\r\n", "\t\t\tCAST(SUM(W2.pct) AS DECIMAL(14, 2)) AS overall_running_pct,\r\n", "\t\t\tCAST ((W1.wait_time_s / W1.waiting_requests_count) AS DECIMAL (14, 4)) AS avg_wait_s,\r\n", "\t\t\tCASE WHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_COUNT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_VIRTUAL_ROOT\u0027 THEN N\u0027[HoBT - Metadata]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_DATASET_PARENT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_SCAN_RANGE_GENERATOR\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027NESTING_TRANSACTION%\u0027 THEN N\u0027[Parallelism]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027LOG_MANAGER\u0027 THEN N\u0027[Log IO]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027TRACE_CONTROLLER\u0027 THEN N\u0027[Trace]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027DBCC_MULTIOBJECT_SCANNER\u0027 THEN N\u0027[Parallelism - DBCC CHECK_]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027FGCB_ADD_REMOVE\u0027 THEN N\u0027[Other IO]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027DATABASE_MIRRORING_CONNECTION\u0027 THEN N\u0027[Mirroring - Busy]\u0027\r\n", "\t\tWHEN W1.latch_class LIKE N\u0027BUFFER\u0027 THEN N\u0027[Buffer Pool]\u0027\r\n", "\t\tELSE N\u0027[Other]\u0027 END AS \u0027latch_category\u0027\r\n", "\t\tFROM #tblFinalLatches AS W1 INNER JOIN #tblFinalLatches AS W2 ON W2.rn <= W1.rn\r\n", "\t\tGROUP BY W1.rn, W1.latch_class, W1.wait_time_s, W1.waiting_requests_count, CAST(W1.pct AS DECIMAL(14, 2))\r\n", "\t\tHAVING SUM(W2.pct) - CAST(W1.pct AS DECIMAL(14, 2)) < 100;\r\n", "\t-- percentage threshold\r\n", "\t\t;WITH\r\n", "\t\t\tLatches\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT latch_class,\r\n", "\t\t\t\t\tCAST(wait_time_ms / 1000.0 AS DECIMAL(14, 2)) AS wait_time_s,\r\n", "\t\t\t\t\twaiting_requests_count,\r\n", "\t\t\t\t\t100.0 * wait_time_ms / SUM(wait_time_ms) OVER() AS pct,\r\n", "\t\t\t\t\tROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn\r\n", "\t\t\t\tFROM sys.dm_os_latch_stats\r\n", "\t\t\t\tWHERE /*latch_class NOT IN (\u0027BUFFER\u0027)\r\n", "\t\t\t\tAND*/ wait_time_ms > 0\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Cumulative_Latches\u0027 AS [Information], W1.latch_class,\r\n", "\t\t\tW1.wait_time_s,\r\n", "\t\t\tW1.waiting_requests_count,\r\n", "\t\t\tCAST(W1.pct AS DECIMAL(14, 2)) AS pct,\r\n", "\t\t\tCAST(SUM(W2.pct) AS DECIMAL(14, 2)) AS overall_running_pct,\r\n", "\t\t\tCAST((W1.wait_time_s / W1.waiting_requests_count) AS DECIMAL (14, 4)) AS avg_wait_s,\r\n", "\t\t\tCASE WHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_COUNT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_VIRTUAL_ROOT\u0027 THEN N\u0027[HoBT - Metadata]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_DATASET_PARENT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_SCAN_RANGE_GENERATOR\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027NESTING_TRANSACTION_FULL\u0027 THEN N\u0027[Parallelism]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027LOG_MANAGER\u0027 THEN N\u0027[IO - Log]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027TRACE_CONTROLLER\u0027 THEN N\u0027[Trace]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027DBCC_MULTIOBJECT_SCANNER \u0027 THEN N\u0027[Parallelism - DBCC CHECK_]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027FGCB_ADD_REMOVE\u0027 THEN N\u0027[IO Operations]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027DATABASE_MIRRORING_CONNECTION \u0027 THEN N\u0027[Mirroring - Busy]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027BUFFER\u0027 THEN N\u0027[Buffer Pool - PAGELATCH or PAGEIOLATCH]\u0027\r\n", "\t\t\tELSE N\u0027Other\u0027 END AS \u0027latch_category\u0027\r\n", "\t\tFROM Latches AS W1\r\n", "\t\t\tINNER JOIN Latches AS W2\r\n", "\t\t\tON W2.rn <= W1.rn\r\n", "\t\tGROUP BY W1.rn, W1.latch_class, W1.wait_time_s, W1.waiting_requests_count, CAST(W1.pct AS DECIMAL(14, 2))\r\n", "\t\tHAVING SUM(W2.pct) - CAST(W1.pct AS DECIMAL(14, 2)) < 100;\r\n", "\t-- percentage threshold\r\n", "\t\t;WITH\r\n", "\t\t\tLatches\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT latch_class,\r\n", "\t\t\t\t\tCAST(wait_time_ms / 1000.0 AS DECIMAL(14, 2)) AS wait_time_s,\r\n", "\t\t\t\t\twaiting_requests_count,\r\n", "\t\t\t\t\t100.0 * wait_time_ms / SUM(wait_time_ms) OVER() AS pct,\r\n", "\t\t\t\t\tROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn\r\n", "\t\t\t\tFROM sys.dm_os_latch_stats (NOLOCK)\r\n", "\t\t\t\tWHERE latch_class NOT IN (\u0027BUFFER\u0027)\r\n", "\t\t\t\t\tAND wait_time_ms > 0\r\n", "\t\t\t)\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Cumulative_Latches_wo_BUFFER\u0027 AS [Information], W1.latch_class,\r\n", "\t\t\tW1.wait_time_s,\r\n", "\t\t\tW1.waiting_requests_count,\r\n", "\t\t\tCAST(W1.pct AS DECIMAL(14, 2)) AS pct,\r\n", "\t\t\tCAST(SUM(W2.pct) AS DECIMAL(14, 2)) AS overall_running_pct,\r\n", "\t\t\tCAST((W1.wait_time_s / W1.waiting_requests_count) AS DECIMAL (14, 4)) AS avg_wait_s,\r\n", "\t\t\tCASE WHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_COUNT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_HOBT_VIRTUAL_ROOT\u0027 THEN N\u0027[HoBT - Metadata]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027ACCESS_METHODS_DATASET_PARENT\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027ACCESS_METHODS_SCAN_RANGE_GENERATOR\u0027\r\n", "\t\t\t\tOR W1.latch_class LIKE N\u0027NESTING_TRANSACTION_FULL\u0027 THEN N\u0027[Parallelism]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027LOG_MANAGER\u0027 THEN N\u0027[IO - Log]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027TRACE_CONTROLLER\u0027 THEN N\u0027[Trace]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027DBCC_MULTIOBJECT_SCANNER \u0027 THEN N\u0027[Parallelism - DBCC CHECK_]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027FGCB_ADD_REMOVE\u0027 THEN N\u0027[IO Operations]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027DATABASE_MIRRORING_CONNECTION \u0027 THEN N\u0027[Mirroring - Busy]\u0027\r\n", "\t\t\tWHEN W1.latch_class LIKE N\u0027BUFFER\u0027 THEN N\u0027[Buffer Pool - PAGELATCH or PAGEIOLATCH]\u0027\r\n", "\t\t\tELSE N\u0027Other\u0027 END AS \u0027latch_category\u0027\r\n", "\t\tFROM Latches AS W1\r\n", "\t\t\tINNER JOIN Latches AS W2\r\n", "\t\t\tON W2.rn <= W1.rn\r\n", "\t\tGROUP BY W1.rn, W1.latch_class, W1.wait_time_s, W1.waiting_requests_count, CAST(W1.pct AS DECIMAL(14, 2))\r\n", "\t\tHAVING SUM(W2.pct) - CAST(W1.pct AS DECIMAL(14, 2)) < 100;\r\n", "\t-- percentage threshold\r\n", "\t\t;WITH\r\n", "\t\t\tcteSpinlocks1\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT name, collisions, spins, spins_per_collision, sleep_time, backoffs\r\n", "\t\t\t\tFROM #tblSpinlocksBefore\r\n", "\t\t\t),\r\n", "\t\t\tcteSpinlocks2\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT name, collisions, spins, spins_per_collision, sleep_time, backoffs\r\n", "\t\t\t\tFROM #tblSpinlocksAfter\r\n", "\t\t\t)\r\n", "\t\tINSERT INTO #tblFinalSpinlocks\r\n", "\t\tSELECT DISTINCT t1.name,\r\n", "\t\t\t(t2.collisions-t1.collisions) AS collisions,\r\n", "\t\t\t(t2.spins-t1.spins) AS spins,\r\n", "\t\t\t(t2.spins_per_collision-t1.spins_per_collision) AS spins_per_collision,\r\n", "\t\t\t(t2.sleep_time-t1.sleep_time) AS sleep_time,\r\n", "\t\t\t(t2.backoffs-t1.backoffs) AS backoffs,\r\n", "\t\t\t100.0 * (t2.spins-t1.spins) / SUM(t2.spins-t1.spins) OVER() AS spins_pct,\r\n", "\t\t\tROW_NUMBER() OVER(ORDER BY t2.spins DESC) AS rn\r\n", "\t\tFROM cteSpinlocks1 t1 INNER JOIN cteSpinlocks2 t2 ON t1.name = t2.name\r\n", "\t\tGROUP BY t1.name, t1.collisions, t2.collisions, t1.spins, t2.spins, t1.spins_per_collision, t2.spins_per_collision, t1.sleep_time, t2.sleep_time, t1.backoffs, t2.backoffs\r\n", "\t\tHAVING (t2.spins-t1.spins) > 0\r\n", "\t\tORDER BY spins DESC;\r\n", "\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Spinlocks_Last_\u0027 + CONVERT(VARCHAR(3), @duration) + \u0027s\u0027 AS [Information], S1.name,\r\n", "\t\t\tS1.collisions, S1.spins, S1.spins_per_collision, S1.sleep_time, S1.backoffs,\r\n", "\t\t\tCAST(S1.spins_pct AS DECIMAL(14, 2)) AS spins_pct,\r\n", "\t\t\tCAST(SUM(S2.spins_pct) AS DECIMAL(14, 2)) AS overall_running_spins_pct\r\n", "\t\tFROM #tblFinalSpinlocks AS S1 INNER JOIN #tblFinalSpinlocks AS S2 ON S2.rn <= S1.rn\r\n", "\t\tGROUP BY S1.rn, S1.name, S1.collisions, S1.spins, S1.spins_per_collision, S1.sleep_time, S1.backoffs, S1.spins_pct\r\n", "\t\tHAVING CAST(SUM(S2.spins_pct) AS DECIMAL(14, 2)) - CAST(S1.spins_pct AS DECIMAL(14, 2)) < 100\r\n", "\t-- percentage threshold\r\n", "\t\tORDER BY spins DESC;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "bc4e7a83-239c-46d6-9897-5a7e3776f7f3", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Worker thread exhaustion subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "eaa061fd-3bb0-435f-8d86-d0610c57c7d9" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Worker thread exhaustion\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE @avgtskcnt int, @workqcnt int\r\n", "\t\tSELECT @avgtskcnt = SUM(runnable_tasks_count)/COUNT(scheduler_id), @workqcnt = SUM(work_queue_count)\r\n", "\t\tFROM sys.dm_os_schedulers\r\n", "\t\tWHERE parent_node_id < 64 AND scheduler_id < 255\r\n", "\t\tIF @avgtskcnt <= 2 AND @workqcnt > 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Worker_thread_exhaustion\u0027 AS [Check], \u0027[WARNING: Possible worker thread exhaustion (schedulers work queue count is \u0027 + CONVERT(NVARCHAR(10), @workqcnt) + \u0027). Because overall runnable tasks count is \u0027 + CONVERT(NVARCHAR(10), @avgtskcnt) + \u0027 (<= 2), indicating the server might not be CPU bound, there might be room to increase max_worker_threads]\u0027 AS [Deviation], \u0027[Configured workers = \u0027 + CONVERT(VARCHAR(10),@mwthreads_count) + \u0027]\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tELSE IF @avgtskcnt > 2 AND @workqcnt > 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Worker_thread_exhaustion\u0027 AS [Check], \u0027[WARNING: Possible worker thread exhaustion (schedulers work queue count is \u0027 + CONVERT(NVARCHAR(10), @workqcnt) + \u0027). Overall runnable tasks count is \u0027 + CONVERT(NVARCHAR(10), @avgtskcnt) + \u0027 (> 2), also indicating the server might be CPU bound]\u0027 AS [Deviation], \u0027[Configured workers = \u0027 + CONVERT(VARCHAR(10),@mwthreads_count) + \u0027]\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Worker_thread_exhaustion\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "d5874262-c7bd-4802-85ce-4d6e20d93c16", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Blocking Chains subsection\r\n", "- Checks for blocking chains taking over 5s.\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "d176b198-9bcf-4c5a-bb29-11b86e32b336" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Blocking Chains\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblBlkChains\u0027))\r\n", "\tDROP TABLE #tblBlkChains;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblBlkChains\u0027))\r\n", "\tCREATE TABLE #tblBlkChains\r\n", "\t\t(\r\n", "\t\t\t[blocked_spid] [smallint],\r\n", "\t\t\t[blocked_spid_status] NVARCHAR(30),\r\n", "\t\t\t[blocked_task_status] NVARCHAR(60),\r\n", "\t\t\t[blocked_spid_wait_type] NVARCHAR(60),\r\n", "\t\t\t[blocked_spid_wait_time_ms] [bigint],\r\n", "\t\t\t[blocked_spid_res_desc] NVARCHAR(1024),\r\n", "\t\t\t[blocked_pageid] [int],\r\n", "\t\t\t[blocked_spid_res_type] VARCHAR(24),\r\n", "\t\t\t[blocked_batch] [xml],\r\n", "\t\t\t[blocked_statement] [xml],\r\n", "\t\t\t[blocked_last_start] [datetime],\r\n", "\t\t\t[blocked_tran_isolation_level] VARCHAR(30),\r\n", "\t\t\t[blocker_spid] [smallint],\r\n", "\t\t\t[is_head_blocker] [int],\r\n", "\t\t\t[blocker_batch] [xml],\r\n", "\t\t\t[blocker_statement] [xml],\r\n", "\t\t\t[blocker_last_start] [datetime],\r\n", "\t\t\t[blocker_tran_isolation_level] VARCHAR(30),\r\n", "\t\t\t[blocked_database] NVARCHAR(128),\r\n", "\t\t\t[blocked_host] NVARCHAR(128),\r\n", "\t\t\t[blocked_program] NVARCHAR(128),\r\n", "\t\t\t[blocked_login] NVARCHAR(128),\r\n", "\t\t\t[blocked_session_comment] VARCHAR(25),\r\n", "\t\t\t[blocked_is_user_process] [bit],\r\n", "\t\t\t[blocker_database] NVARCHAR(128),\r\n", "\t\t\t[blocker_host] NVARCHAR(128),\r\n", "\t\t\t[blocker_program] NVARCHAR(128),\r\n", "\t\t\t[blocker_login] NVARCHAR(128),\r\n", "\t\t\t[blocker_session_comment] VARCHAR(25),\r\n", "\t\t\t[blocker_is_user_process] [bit]\r\n", "\t\t)\r\n", "\t\tINSERT INTO #tblBlkChains\r\n", "\t\tSELECT\r\n", "\t\t-- blocked\r\n", "\t\t\tes.session_id AS blocked_spid,\r\n", "\t\t\tes.[status] AS [blocked_spid_status],\r\n", "\t\t\tot.task_state AS [blocked_task_status],\r\n", "\t\t\towt.wait_type AS blocked_spid_wait_type,\r\n", "\t\t\tCOALESCE(owt.wait_duration_ms, ABS(CONVERT(BIGINT,(DATEDIFF(mi, es.last_request_start_time, GETDATE())))*60)) AS blocked_spid_wait_time_ms,\r\n", "\t\t--er.total_elapsed_time AS blocked_elapsed_time_ms,\r\n", "\t\t\t/* \r\n", "\t\t\tCheck sys.dm_os_waiting_tasks for Exchange wait types in http://technet.microsoft.com/library/ms188743.aspx.\r\n", "\t\t\t- Wait Resource e_waitPipeNewRow in CXPACKET waits – Producer waiting on consumer for a packet to fill.\r\n", "\t\t\t- Wait Resource e_waitPipeGetRow in CXPACKET waits – Consumer waiting on producer to fill a packet.\r\n", "\t\t*/\r\n", "\t\t\towt.resource_description AS blocked_spid_res_desc,\r\n", "\t\t\towt.pageid AS blocked_pageid,\r\n", "\t\t\tCASE WHEN owt.pageid = 1 OR owt.pageid % 8088 = 0 THEN \u0027Is_PFS_Page\u0027\r\n", "\t\t\tWHEN owt.pageid = 2 OR owt.pageid % 511232 = 0 THEN \u0027Is_GAM_Page\u0027\r\n", "\t\t\tWHEN owt.pageid = 3 OR (owt.pageid - 1) % 511232 = 0 THEN \u0027Is_SGAM_Page\u0027\r\n", "\t\t\tWHEN owt.pageid IS NULL THEN NULL\r\n", "\t\t\tELSE \u0027Is_not_PFS_GAM_SGAM_page\u0027 END AS blocked_spid_res_type,\r\n", "\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\tqt.[text],\r\n", "\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027) \r\n", "\t\t\tAS [text()]\r\n", "\t\t\tFROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt\r\n", "\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [blocked_batch],\r\n", "\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\tSUBSTRING(qt2.text, \r\n", "\t\t\t1+(CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END),\r\n", "\t\t\t1+(CASE WHEN er.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er.statement_end_offset/2 END - (CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END))),\r\n", "\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027) \r\n", "\t\t\tAS [text()]\r\n", "\t\t\tFROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt2\r\n", "\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [blocked_statement],\r\n", "\t\t\tes.last_request_start_time AS blocked_last_start,\r\n", "\t\t\tLEFT (CASE COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)\r\n", "\t\t\tWHEN 0 THEN \u00270-Unspecified\u0027 \r\n", "\t\t\tWHEN 1 THEN \u00271-ReadUncommitted(NOLOCK)\u0027 \r\n", "\t\t\tWHEN 2 THEN \u00272-ReadCommitted\u0027 \r\n", "\t\t\tWHEN 3 THEN \u00273-RepeatableRead\u0027 \r\n", "\t\t\tWHEN 4 THEN \u00274-Serializable\u0027 \r\n", "\t\t\tWHEN 5 THEN \u00275-Snapshot\u0027\r\n", "\t\t\tELSE CONVERT (VARCHAR(30), COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)) + \u0027-UNKNOWN\u0027 \r\n", "\t\tEND, 30) AS blocked_tran_isolation_level,\r\n", "\t\t-- blocker\r\n", "\t\t\ter.blocking_session_id As blocker_spid,\r\n", "\t\t\tCASE \r\n", "\t\t-- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others\r\n", "\t\t\tWHEN (er2.session_id IS NULL OR owt.blocking_session_id IS NULL) AND (er.blocking_session_id = 0 OR er.session_id IS NULL) THEN 1\r\n", "\t\t-- session is either not blocking someone, or is blocking someone but is blocked by another party\r\n", "\t\t\tELSE 0\r\n", "\t\tEND AS is_head_blocker,\r\n", "\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\tqt2.[text],\r\n", "\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027) \r\n", "\t\t\tAS [text()]\r\n", "\t\t\tFROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2\r\n", "\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [blocker_batch],\r\n", "\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\tSUBSTRING(qt2.text, \r\n", "\t\t\t1+(CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END),\r\n", "\t\t\t1+(CASE WHEN er2.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er2.statement_end_offset/2 END - (CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END))),\r\n", "\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027) \r\n", "\t\t\tAS [text()]\r\n", "\t\t\tFROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2\r\n", "\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [blocker_statement],\r\n", "\t\t\tes2.last_request_start_time AS blocker_last_start,\r\n", "\t\t\tLEFT (CASE COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)\r\n", "\t\t\tWHEN 0 THEN \u00270-Unspecified\u0027 \r\n", "\t\t\tWHEN 1 THEN \u00271-ReadUncommitted(NOLOCK)\u0027 \r\n", "\t\t\tWHEN 2 THEN \u00272-ReadCommitted\u0027 \r\n", "\t\t\tWHEN 3 THEN \u00273-RepeatableRead\u0027 \r\n", "\t\t\tWHEN 4 THEN \u00274-Serializable\u0027 \r\n", "\t\t\tWHEN 5 THEN \u00275-Snapshot\u0027 \r\n", "\t\t\tELSE CONVERT (VARCHAR(30), COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)) + \u0027-UNKNOWN\u0027 \r\n", "\t\tEND, 30) AS blocker_tran_isolation_level,\r\n", "\t\t-- blocked - other data\r\n", "\t\t\tDB_NAME(er.database_id) AS blocked_database,\r\n", "\t\t\tes.[host_name] AS blocked_host,\r\n", "\t\t\tes.[program_name] AS blocked_program,\r\n", "\t\t\tes.login_name AS blocked_login,\r\n", "\t\t\tCASE WHEN es.session_id = -2 THEN \u0027Orphaned_distributed_tran\u0027 \r\n", "\t\t\tWHEN es.session_id = -3 THEN \u0027Defered_recovery_tran\u0027 \r\n", "\t\t\tWHEN es.session_id = -4 THEN \u0027Unknown_tran\u0027 ELSE NULL END AS blocked_session_comment,\r\n", "\t\t\tes.is_user_process AS [blocked_is_user_process],\r\n", "\t\t-- blocker - other data\r\n", "\t\t\tDB_NAME(er2.database_id) AS blocker_database,\r\n", "\t\t\tes2.[host_name] AS blocker_host,\r\n", "\t\t\tes2.[program_name] AS blocker_program,\r\n", "\t\t\tes2.login_name AS blocker_login,\r\n", "\t\t\tCASE WHEN es2.session_id = -2 THEN \u0027Orphaned_distributed_tran\u0027 \r\n", "\t\t\tWHEN es2.session_id = -3 THEN \u0027Defered_recovery_tran\u0027 \r\n", "\t\t\tWHEN es2.session_id = -4 THEN \u0027Unknown_tran\u0027 ELSE NULL END AS blocker_session_comment,\r\n", "\t\t\tes2.is_user_process AS [blocker_is_user_process]\r\n", "\t\tFROM sys.dm_exec_sessions es\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_os_tasks ot ON er.session_id = ot.session_id AND er.request_id = ot.request_id\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_exec_sessions es2 ON er.blocking_session_id = es2.session_id\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_exec_requests er2 ON es2.session_id = er2.session_id\r\n", "\t\t\tLEFT OUTER JOIN sys.dm_exec_connections ec2 ON es2.session_id = ec2.session_id\r\n", "\t\t\tLEFT OUTER JOIN\r\n", "\t\t\t(\r\n", "\t-- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as \r\n", "\t-- waiting for several different threads. This will cause that thread to show up in multiple rows \r\n", "\t-- in our grid, which we don\u0027t want. Use ROW_NUMBER to select the longest wait for each thread, \r\n", "\t-- and use it as representative of the other wait relationships this thread is involved in. \r\n", "\t\tSELECT waiting_task_address, session_id, exec_context_id, wait_duration_ms,\r\n", "\t\t\t\twait_type, resource_address, blocking_task_address, blocking_session_id,\r\n", "\t\t\t\tblocking_exec_context_id, resource_description,\r\n", "\t\t\t\tCASE WHEN [wait_type] LIKE \u0027PAGE%\u0027 AND [resource_description] LIKE \u0027%:%\u0027 THEN CAST(RIGHT([resource_description], LEN([resource_description]) - CHARINDEX(\u0027:\u0027, [resource_description], LEN([resource_description])-CHARINDEX(\u0027:\u0027, REVERSE([resource_description])))) AS int)\r\n", "\t\t\t\tELSE NULL END AS pageid,\r\n", "\t\t\t\tROW_NUMBER() OVER (PARTITION BY waiting_task_address ORDER BY wait_duration_ms DESC) AS row_num\r\n", "\t\t\tFROM sys.dm_os_waiting_tasks\r\n", "\t\t\tWHERE wait_type <> \u0027SP_SERVER_DIAGNOSTICS_SLEEP\u0027\r\n", "\t) owt ON ot.task_address = owt.waiting_task_address AND owt.row_num = 1\r\n", "\t--OUTER APPLY sys.dm_exec_sql_text (er.sql_handle) est\r\n", "\t--OUTER APPLY sys.dm_exec_query_plan (er.plan_handle) eqp\r\n", "\t\tWHERE es.session_id <> @@SPID AND es.is_user_process = 1\r\n", "\t\t\tAND ((owt.wait_duration_ms/1000) > 5 OR (er.total_elapsed_time/1000) > 5 OR er.total_elapsed_time IS NULL) --Only report blocks > 5 Seconds plus head blocker\r\n", "\t\t\tAND (es.session_id IN (SELECT er3.blocking_session_id\r\n", "\t\t\tFROM sys.dm_exec_requests er3) OR er.blocking_session_id IS NOT NULL)\r\n", "\t\tORDER BY blocked_spid, is_head_blocker DESC, blocked_spid_wait_time_ms DESC, blocker_spid;\r\n", "\t\tIF (SELECT COUNT(blocked_spid)\r\n", "\t\tFROM #tblBlkChains\r\n", "\t\tWHERE CONVERT(VARCHAR(max), blocked_batch) <> \u0027sp_server_diagnostics\u0027) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Blocking_Chains_over_5s\u0027 AS [Check], \u0027[WARNING: Blocking chains in excess of 5s were found.]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Blocking_Chains_over_5s\u0027 AS [Information], [blocked_spid], [blocked_spid_status], [blocked_task_status],\r\n", "\t\t\t\t[blocked_spid_wait_type], [blocked_spid_wait_time_ms], [blocked_spid_res_desc], [blocked_pageid], [blocked_spid_res_type],\r\n", "\t\t\t\t[blocked_batch], [blocked_statement], [blocked_last_start], [blocked_tran_isolation_level], [blocker_spid], [is_head_blocker],\r\n", "\t\t\t\t[blocker_batch], [blocker_statement], [blocker_last_start], [blocker_tran_isolation_level], [blocked_database],\r\n", "\t\t\t\t[blocked_host], [blocked_program], [blocked_login], [blocked_session_comment], [blocked_is_user_process], [blocker_database],\r\n", "\t\t\t\t[blocker_host], [blocker_program], [blocker_login], [blocker_session_comment], [blocker_is_user_process]\r\n", "\t\t\tFROM #tblBlkChains\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Blocking_Chains_over_5s\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "32282bce-5764-4d89-b0ba-a90a8d5be71c", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Plan use ratio subsection\r\n", "- Refer to BOL for more information (https://docs.microsoft.com/sql/database-engine/configure-windows/optimize-for-ad-hoc-workloads-server-configuration-option)\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "d55b069d-224e-4512-aaa0-23bcc604ac0e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Plan use ratio\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT SUM(CAST(size_in_bytes AS bigint))/1024/1024 AS Size_MB\r\n", "\t\tFROM sys.dm_exec_cached_plans (NOLOCK)\r\n", "\t\tWHERE cacheobjtype LIKE \u0027%Plan%\u0027 AND usecounts = 1) \r\n", "\t\t>= \r\n", "\t\t(SELECT SUM(CAST(size_in_bytes AS bigint))/1024/1024 AS Size_MB\r\n", "\t\tFROM sys.dm_exec_cached_plans (NOLOCK)\r\n", "\t\tWHERE cacheobjtype LIKE \u0027%Plan%\u0027 AND usecounts > 1)\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Plan_use_ratio\u0027 AS [Check], \u0027[WARNING: Amount of single use plans in cache is high]\u0027 AS [Deviation], CASE WHEN @sqlmajorver > 9 AND @adhoc = 0 THEN \u0027[Consider enabling the Optimize for ad hoc workloads setting on heavy OLTP ad-hoc workloads to conserve resources]\u0027 ELSE \u0027\u0027 END AS [Comment]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Plan_use_ratio\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation], \u0027\u0027 AS [Comment]\r\n", "\t\tEND;\r\n", "\t--High number of cached plans with usecounts = 1.\r\n", "\t\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Plan_use_ratio\u0027 AS [Information], objtype, cacheobjtype, AVG(CAST(usecounts AS bigint)) AS Avg_UseCount_perPlan, SUM(refcounts) AS AllRefObjects, SUM(CAST(size_in_bytes AS bigint))/1024/1024 AS Size_MB\r\n", "\t\t\tFROM sys.dm_exec_cached_plans (NOLOCK)\r\n", "\t\t\tWHERE cacheobjtype LIKE \u0027%Plan%\u0027 AND usecounts = 1\r\n", "\t\t\tGROUP BY objtype, cacheobjtype\r\n", "\t\tUNION ALL\r\n", "\t\t--High number of cached plans with usecounts > 1.\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Plan_use_ratio\u0027 AS [Information], objtype, cacheobjtype, AVG(CAST(usecounts AS bigint)) AS Avg_UseCount_perPlan, SUM(refcounts) AS AllRefObjects, SUM(CAST(size_in_bytes AS bigint))/1024/1024 AS Size_MB\r\n", "\t\t\tFROM sys.dm_exec_cached_plans (NOLOCK)\r\n", "\t\t\tWHERE cacheobjtype LIKE \u0027%Plan%\u0027 AND usecounts > 1\r\n", "\t\t\tGROUP BY objtype, cacheobjtype\r\n", "\t\tORDER BY objtype, cacheobjtype;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "524985c3-7286-4bd4-9f38-d52f017dad1b", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Hints usage subsection\r\n", "- Refer to \"Hints\" BOL entry for more information (https://docs.microsoft.com/sql/t-sql/queries/hints-transact-sql)\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "2783cc7e-b2b8-4400-b175-4291c1c67235" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Hints usage\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT([counter])\r\n", "\t\tFROM sys.dm_exec_query_optimizer_info\r\n", "\t\tWHERE ([counter] = \u0027order hint\u0027 OR [counter] = \u0027join hint\u0027) AND occurrence > 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (N\u0027 |-Hints are being used - finding usage in SQL modules\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\t/*DECLARE @dbid int, @dbname VARCHAR(1000), @sqlcmd NVARCHAR(4000)*/\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHints\u0027))\r\n", "\t\tDROP TABLE #tblHints;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHints\u0027))\r\n", "\t\tCREATE TABLE #tblHints\r\n", "\t\t\t(\r\n", "\t\t\t\t[DBName] sysname,\r\n", "\t\t\t\t[Schema] VARCHAR(100),\r\n", "\t\t\t\t[Object] VARCHAR(255),\r\n", "\t\t\t\t[Type] VARCHAR(100),\r\n", "\t\t\t\tHint VARCHAR(30)\r\n", "\t\t\t);\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 0;\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\t\tIF (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], ss.name AS [Schema_Name], so.name AS [Object_Name], so.type_desc, \r\n", "\tCASE WHEN sm.[definition] LIKE \u0027\u0027%FORCE ORDER%\u0027\u0027 THEN \u0027\u0027[FORCE ORDER Hint]\u0027\u0027\r\n", "\tWHEN sm.[definition] LIKE \u0027\u0027%MERGE JOIN%\u0027\u0027\r\n", "\t\tOR sm.[definition] LIKE \u0027\u0027%LOOP JOIN%\u0027\u0027\r\n", "\t\tOR sm.[definition] LIKE \u0027\u0027%HASH JOIN%\u0027\u0027 THEN \u0027\u0027[JOIN Hint]\u0027\u0027 END AS Hint\r\n", "FROM sys.sql_modules sm\r\n", "INNER JOIN sys.objects so ON sm.[object_id] = so.[object_id]\r\n", "INNER JOIN sys.schemas ss ON so.[schema_id] = ss.[schema_id]\r\n", "WHERE (sm.[definition] LIKE \u0027\u0027%FORCE ORDER%\u0027\u0027\r\n", "\tOR sm.[definition] LIKE \u0027\u0027%MERGE JOIN%\u0027\u0027\r\n", "\tOR sm.[definition] LIKE \u0027\u0027%LOOP JOIN%\u0027\u0027\r\n", "\tOR sm.[definition] LIKE \u0027\u0027%HASH JOIN%\u0027\u0027) \r\n", "AND OBJECTPROPERTY(sm.[object_id],\u0027\u0027IsMSShipped\u0027\u0027) = 0;\u0027\r\n", "\t\t\t\t\tBEGIN TRY\r\n", "\t\t\t\t\tDECLARE @Message varchar(120)\r\n", "\t\t\t\t\tSET @Message = \u0027 |-Checking Hints For \u0027 + QUOTENAME(@dbname)\r\n", "\t\t\t\t\tRAISERROR (@Message , 10, 1) WITH NOWAIT\r\n", "\t\t\t\t\tINSERT INTO #tblHints\r\n", "\t\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\t\tEND TRY\r\n", "\t\t\t\tBEGIN CATCH\r\n", "\t\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027Hints usage subsection - Error raised in TRY block. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\t\tEND CATCH\r\n", "\t\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tSET isdone = 1\r\n", "\t\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND;\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Hints_usage\u0027 AS [Check], \u0027[WARNING: Hints are being used. These can hinder the QO ability to optimize queries]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Hints_usage\u0027 AS [Information], CASE WHEN [counter] = \u0027order hint\u0027 THEN \u0027[FORCE ORDER Hint]\u0027 WHEN [counter] = \u0027join hint\u0027 THEN \u0027[JOIN Hint]\u0027 END AS [Hint], occurrence\r\n", "\t\t\tFROM sys.dm_exec_query_optimizer_info (NOLOCK)\r\n", "\t\t\tWHERE ([counter] = \u0027order hint\u0027 OR [counter] = \u0027join hint\u0027) AND occurrence > 1;\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblHints\r\n", "\t\t\tWHERE [DBName] IS NOT NULL) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Hints_usage_in_Objects\u0027 AS [Information], [DBName], [Schema], [Object], [Type], Hint, \u0027\u0027 AS Comment\r\n", "\t\t\t\tFROM #tblHints (NOLOCK)\r\n", "\t\t\t\tORDER BY [DBName], Hint, [Type], [Object];\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Hints_usage_in_Objects\u0027 AS [Information], NULL AS [DBName], NULL AS [Schema], NULL AS [Object], NULL AS [Type],\r\n", "\t\t\t\t\tCASE WHEN [counter] = \u0027order hint\u0027 THEN \u0027[FORCE ORDER Hint]\u0027 WHEN [counter] = \u0027join hint\u0027 THEN \u0027[JOIN Hint]\u0027 END AS [Hint], \u0027[INFORMATION: Hints may be in use with ad-hoc code]\u0027 AS Comment\r\n", "\t\t\t\tFROM sys.dm_exec_query_optimizer_info (NOLOCK)\r\n", "\t\t\t\tWHERE ([counter] = \u0027order hint\u0027 OR [counter] = \u0027join hint\u0027) AND occurrence > 1;\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Hints_usage\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "056a12d1-b138-4f99-8c3f-e64a6a1914ce", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Cached Query Plans issues subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "8fb4055d-edc3-45be-a9e9-2337cb0a8f1a" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Cached Query Plans issues\u0027, 10, 1) WITH NOWAIT\r\n", "\t--DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(500), @sqlmajorver int, @sqlminorver int, @sqlbuild int\r\n", "\t--SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff);\r\n", "\t--SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff);\r\n", "\t--SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_exec_query_stats\u0027)) \r\n", "\tDROP TABLE #tmp_dm_exec_query_stats;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_exec_query_stats\u0027)) \r\n", "\tCREATE TABLE #tmp_dm_exec_query_stats\r\n", "\t\t(\r\n", "\t\t\t[plan_id] [int] NOT NULL IDENTITY(1, 1),\r\n", "\t\t\t[sql_handle] [varbinary](64) NOT NULL,\r\n", "\t\t\t[statement_start_offset] [int] NOT NULL,\r\n", "\t\t\t[statement_end_offset] [int] NOT NULL,\r\n", "\t\t\t[plan_generation_num] [bigint] NOT NULL,\r\n", "\t\t\t[plan_handle] [varbinary](64) NOT NULL,\r\n", "\t\t\t[creation_time] [datetime] NOT NULL,\r\n", "\t\t\t[last_execution_time] [datetime] NOT NULL,\r\n", "\t\t\t[execution_count] [bigint] NOT NULL,\r\n", "\t\t\t[total_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[total_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[last_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[min_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[max_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[total_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[last_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[min_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[max_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[total_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[last_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[min_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[max_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[total_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[total_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t--2008 only\r\n", "\t\t\t[query_hash] [binary](8) NULL,\r\n", "\t\t\t[query_plan_hash] [binary](8) NULL,\r\n", "\t\t--2008R2 only\r\n", "\t\t\t[total_rows] bigint NULL,\r\n", "\t\t\t[last_rows] bigint NULL,\r\n", "\t\t\t[min_rows] bigint NULL,\r\n", "\t\t\t[max_rows] bigint NULL,\r\n", "\t\t--post 2012 SP3, 2014 SP2 and 2016\r\n", "\t\t\t[Last_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_dop] bigint NULL,\r\n", "\t\t\t[Min_dop] bigint NULL,\r\n", "\t\t\t[Max_dop] bigint NULL,\r\n", "\t\t\t[Total_dop] bigint NULL,\r\n", "\t\t\t[Last_reserved_threads] bigint NULL,\r\n", "\t\t\t[Min_reserved_threads] bigint NULL,\r\n", "\t\t\t[Max_reserved_threads] bigint NULL,\r\n", "\t\t\t[Total_reserved_threads] bigint NULL,\r\n", "\t\t\t[Last_used_threads] bigint NULL,\r\n", "\t\t\t[Min_used_threads] bigint NULL,\r\n", "\t\t\t[Max_used_threads] bigint NULL,\r\n", "\t\t\t[Total_used_threads] bigint NULL,\r\n", "\t\t\t[Grant2Used_Ratio] float NULL\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dm_exec_query_stats\u0027)) \r\n", "\tDROP TABLE #dm_exec_query_stats;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dm_exec_query_stats\u0027)) \r\n", "\tCREATE TABLE #dm_exec_query_stats\r\n", "\t\t(\r\n", "\t\t\t[plan_id] [int] NOT NULL IDENTITY(1, 1),\r\n", "\t\t\t[sql_handle] [varbinary](64) NOT NULL,\r\n", "\t\t\t[statement_start_offset] [int] NOT NULL,\r\n", "\t\t\t[statement_end_offset] [int] NOT NULL,\r\n", "\t\t\t[plan_generation_num] [bigint] NOT NULL,\r\n", "\t\t\t[plan_handle] [varbinary](64) NOT NULL,\r\n", "\t\t\t[creation_time] [datetime] NOT NULL,\r\n", "\t\t\t[last_execution_time] [datetime] NOT NULL,\r\n", "\t\t\t[execution_count] [bigint] NOT NULL,\r\n", "\t\t\t[total_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_worker_time] [bigint] NOT NULL,\r\n", "\t\t\t[total_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[last_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[min_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[max_physical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[total_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[last_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[min_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[max_logical_writes] [bigint] NOT NULL,\r\n", "\t\t\t[total_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[last_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[min_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[max_logical_reads] [bigint] NOT NULL,\r\n", "\t\t\t[total_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_clr_time] [bigint] NOT NULL,\r\n", "\t\t\t[total_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[last_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[min_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t\t[max_elapsed_time] [bigint] NOT NULL,\r\n", "\t\t--2008 only\r\n", "\t\t\t[query_hash] [binary](8) NULL,\r\n", "\t\t\t[query_plan_hash] [binary](8) NULL,\r\n", "\t\t--2008R2 only\r\n", "\t\t\t[total_rows] bigint NULL,\r\n", "\t\t\t[last_rows] bigint NULL,\r\n", "\t\t\t[min_rows] bigint NULL,\r\n", "\t\t\t[max_rows] bigint NULL,\r\n", "\t\t--post 2012 SP3, 2014 SP2 and 2016\r\n", "\t\t\t[Last_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_used_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Min_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Max_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Total_ideal_grant_kb] bigint NULL,\r\n", "\t\t\t[Last_dop] bigint NULL,\r\n", "\t\t\t[Min_dop] bigint NULL,\r\n", "\t\t\t[Max_dop] bigint NULL,\r\n", "\t\t\t[Total_dop] bigint NULL,\r\n", "\t\t\t[Last_reserved_threads] bigint NULL,\r\n", "\t\t\t[Min_reserved_threads] bigint NULL,\r\n", "\t\t\t[Max_reserved_threads] bigint NULL,\r\n", "\t\t\t[Total_reserved_threads] bigint NULL,\r\n", "\t\t\t[Last_used_threads] bigint NULL,\r\n", "\t\t\t[Min_used_threads] bigint NULL,\r\n", "\t\t\t[Max_used_threads] bigint NULL,\r\n", "\t\t\t[Total_used_threads] bigint NULL,\r\n", "\t\t\t[Grant2Used_Ratio] float NULL,\r\n", "\t\t--end\r\n", "\t\t\t[query_plan] [xml] NULL,\r\n", "\t\t\t[text] [nvarchar](MAX) COLLATE database_default NULL,\r\n", "\t\t\t[text_filtered] [nvarchar](MAX) COLLATE database_default NULL\r\n", "\t\t)\r\n", "\t\tIF @sqlmajorver = 9\r\n", "\tBEGIN\r\n", "\t\t--CPU \r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK) \r\n", "\t\t--ORDER BY qs.total_worker_time DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_worker_time DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_worker_time DESC\u0027);\r\n", "\t\t--IO\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_logical_reads DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_logical_reads DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_logical_reads DESC\u0027);\r\n", "\t\t--Recompiles\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.plan_generation_num DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.plan_generation_num DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.plan_generation_num DESC\u0027);\r\n", "\t\tEND\r\n", "\tELSE IF @sqlmajorver = 10 AND (@sqlminorver = 0 OR (@sqlminorver = 50 AND @sqlbuild < 2500))\r\n", "\tBEGIN\r\n", "\t\t--CPU \r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_worker_time DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_worker_time DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_worker_time DESC\u0027);\r\n", "\t\t--IO\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_logical_reads DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_logical_reads DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_logical_reads DESC\u0027);\r\n", "\t\t--Recompiles\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.plan_generation_num DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.plan_generation_num DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.plan_generation_num DESC\u0027);\r\n", "\t\tEND\r\n", "\tELSE IF (@sqlmajorver = 10 AND @sqlminorver = 50) OR (@sqlmajorver = 11 AND @sqlbuild < 6020) OR (@sqlmajorver = 12 AND @sqlbuild < 5000)\r\n", "\tBEGIN\r\n", "\t\t--CPU \r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_worker_time DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_worker_time DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_worker_time DESC\u0027);\r\n", "\t\t--IO\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_logical_reads DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_logical_reads DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_logical_reads DESC\u0027);\r\n", "\t\t--Recompiles\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.plan_generation_num DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.plan_generation_num DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows]\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.plan_generation_num DESC\u0027);\r\n", "\t\tEND\r\n", "\tELSE IF (@sqlmajorver = 11 AND @sqlbuild >= 6020) OR (@sqlmajorver = 12 AND @sqlbuild >= 5000) OR @sqlmajorver >= 13\r\n", "\tBEGIN\r\n", "\t\t--CPU \r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],[Grant2Used_Ratio])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_worker_time DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],COALESCE((([Total_used_grant_kb] * 100.00) / NULLIF([Total_grant_kb],0)), 0) AS Grant2Used_Ratio\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_worker_time DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple, Grant2Used_Ratio\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads], Grant2Used_Ratio\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_worker_time DESC\u0027);\r\n", "\t\t--IO\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],[Grant2Used_Ratio])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.total_logical_reads DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],COALESCE((([Total_used_grant_kb] * 100.00) / NULLIF([Total_grant_kb],0)), 0) AS Grant2Used_Ratio\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.total_logical_reads DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple, Grant2Used_Ratio\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads], Grant2Used_Ratio\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.total_logical_reads DESC\u0027);\r\n", "\t\t--Recompiles\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],[Grant2Used_Ratio])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.plan_generation_num DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],COALESCE((([Total_used_grant_kb] * 100.00) / NULLIF([Total_grant_kb],0)), 0) AS Grant2Used_Ratio\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "ORDER BY qs.plan_generation_num DESC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple, Grant2Used_Ratio\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads], Grant2Used_Ratio\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.plan_generation_num DESC\u0027);\r\n", "\t\t--Mem Grants\r\n", "\t\t\tINSERT INTO #tmp_dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],[Grant2Used_Ratio])\r\n", "\t\t--EXEC (\u0027SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads]\r\n", "\t\t--FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "\t\t--ORDER BY qs.Total_grant_kb DESC\u0027);\r\n", "\t\t\tEXEC (\u0027;WITH XMLNAMESPACES (DEFAULT \u0027\u0027http://schemas.microsoft.com/sqlserver/2004/07/showplan\u0027\u0027), \r\n", "TopSearch AS (SELECT DISTINCT TOP 25 [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],COALESCE((([Total_used_grant_kb] * 100.00) / NULLIF([Total_grant_kb],0)), 0) AS Grant2Used_Ratio\r\n", "FROM sys.dm_exec_query_stats qs (NOLOCK)\r\n", "WHERE [Total_used_grant_kb] > 0\r\n", "ORDER BY Total_used_grant_kb DESC, COALESCE((([Total_used_grant_kb] * 100.00) / NULLIF([Total_grant_kb],0)), 0) ASC),\r\n", "TopFineSearch AS (SELECT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],ix.query(\u0027\u0027.\u0027\u0027) AS StmtSimple, Grant2Used_Ratio\r\n", "FROM TopSearch ts\r\n", "OUTER APPLY sys.dm_exec_query_plan(ts.plan_handle) qp\r\n", "CROSS APPLY qp.query_plan.nodes(\u0027\u0027//StmtSimple\u0027\u0027) AS p(ix))\r\n", "SELECT DISTINCT [sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads], Grant2Used_Ratio\r\n", "FROM TopFineSearch tfs\r\n", "CROSS APPLY StmtSimple.nodes(\u0027\u0027//Object\u0027\u0027) AS o(obj)\r\n", "WHERE obj.value(\u0027\u0027@Database\u0027\u0027,\u0027\u0027sysname\u0027\u0027) NOT IN (\u0027\u0027[master]\u0027\u0027,\u0027\u0027[mssqlsystemresource]\u0027\u0027)\r\n", "ORDER BY tfs.Grant2Used_Ratio ASC\u0027);\r\n", "\t\tEND;\r\n", "\t-- Remove duplicates before inserting XML\r\n", "\t\tIF @sqlmajorver = 9\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time])\r\n", "\t\t\tSELECT DISTINCT [sql_handle], [statement_start_offset], [statement_end_offset], [plan_generation_num], [plan_handle], [creation_time], [last_execution_time], [execution_count], [total_worker_time], [last_worker_time], [min_worker_time], [max_worker_time], [total_physical_reads], [last_physical_reads], [min_physical_reads], [max_physical_reads], [total_logical_writes], [last_logical_writes], [min_logical_writes], [max_logical_writes], [total_logical_reads], [last_logical_reads], [min_logical_reads], [max_logical_reads], [total_clr_time], [last_clr_time], [min_clr_time], [max_clr_time], [total_elapsed_time], [last_elapsed_time], [min_elapsed_time], [max_elapsed_time]\r\n", "\t\t\tFROM #tmp_dm_exec_query_stats;\r\n", "\t\tEND\r\n", "\tELSE IF @sqlmajorver = 10 AND (@sqlminorver = 0 OR (@sqlminorver = 50 AND @sqlbuild < 2500))\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash])\r\n", "\t\t\tSELECT DISTINCT [sql_handle], [statement_start_offset], [statement_end_offset], [plan_generation_num], [plan_handle], [creation_time], [last_execution_time], [execution_count], [total_worker_time], [last_worker_time], [min_worker_time], [max_worker_time], [total_physical_reads], [last_physical_reads], [min_physical_reads], [max_physical_reads], [total_logical_writes], [last_logical_writes], [min_logical_writes], [max_logical_writes], [total_logical_reads], [last_logical_reads], [min_logical_reads], [max_logical_reads], [total_clr_time], [last_clr_time], [min_clr_time], [max_clr_time], [total_elapsed_time], [last_elapsed_time], [min_elapsed_time], [max_elapsed_time], [query_hash], [query_plan_hash]\r\n", "\t\t\tFROM #tmp_dm_exec_query_stats;\r\n", "\t\tEND\r\n", "\tELSE IF (@sqlmajorver = 10 AND @sqlminorver = 50) OR (@sqlmajorver = 11 AND @sqlbuild < 6020) OR (@sqlmajorver = 12 AND @sqlbuild < 5000)\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows])\r\n", "\t\t\tSELECT DISTINCT [sql_handle], [statement_start_offset], [statement_end_offset], [plan_generation_num], [plan_handle], [creation_time], [last_execution_time], [execution_count], [total_worker_time], [last_worker_time], [min_worker_time], [max_worker_time], [total_physical_reads], [last_physical_reads], [min_physical_reads], [max_physical_reads], [total_logical_writes], [last_logical_writes], [min_logical_writes], [max_logical_writes], [total_logical_reads], [last_logical_reads], [min_logical_reads], [max_logical_reads], [total_clr_time], [last_clr_time], [min_clr_time], [max_clr_time], [total_elapsed_time], [last_elapsed_time], [min_elapsed_time], [max_elapsed_time], [query_hash], [query_plan_hash], [total_rows], [last_rows], [min_rows], [max_rows]\r\n", "\t\t\tFROM #tmp_dm_exec_query_stats;\r\n", "\t\tEND\r\n", "\tELSE IF (@sqlmajorver = 11 AND @sqlbuild >= 6020) OR (@sqlmajorver = 12 AND @sqlbuild >= 5000) OR @sqlmajorver >= 13\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #dm_exec_query_stats\r\n", "\t\t\t\t([sql_handle],[statement_start_offset],[statement_end_offset],[plan_generation_num],[plan_handle],[creation_time],[last_execution_time],[execution_count],[total_worker_time],[last_worker_time],[min_worker_time],[max_worker_time],[total_physical_reads],[last_physical_reads],[min_physical_reads],[max_physical_reads],[total_logical_writes],[last_logical_writes],[min_logical_writes],[max_logical_writes],[total_logical_reads],[last_logical_reads],[min_logical_reads],[max_logical_reads],[total_clr_time],[last_clr_time],[min_clr_time],[max_clr_time],[total_elapsed_time],[last_elapsed_time],[min_elapsed_time],[max_elapsed_time],[query_hash],[query_plan_hash],[total_rows],[last_rows],[min_rows],[max_rows],[Last_grant_kb],[Min_grant_kb],[Max_grant_kb],[Total_grant_kb],[Last_used_grant_kb],[Min_used_grant_kb],[Max_used_grant_kb],[Total_used_grant_kb],[Last_ideal_grant_kb],[Min_ideal_grant_kb],[Max_ideal_grant_kb],[Total_ideal_grant_kb],[Last_dop],[Min_dop],[Max_dop],[Total_dop],[Last_reserved_threads],[Min_reserved_threads],[Max_reserved_threads],[Total_reserved_threads],[Last_used_threads],[Min_used_threads],[Max_used_threads],[Total_used_threads],[Grant2Used_Ratio])\r\n", "\t\t\tSELECT DISTINCT [sql_handle], [statement_start_offset], [statement_end_offset], [plan_generation_num], [plan_handle], [creation_time], [last_execution_time], [execution_count], [total_worker_time], [last_worker_time], [min_worker_time], [max_worker_time], [total_physical_reads], [last_physical_reads], [min_physical_reads], [max_physical_reads], [total_logical_writes], [last_logical_writes], [min_logical_writes], [max_logical_writes], [total_logical_reads], [last_logical_reads], [min_logical_reads], [max_logical_reads], [total_clr_time], [last_clr_time], [min_clr_time], [max_clr_time], [total_elapsed_time], [last_elapsed_time], [min_elapsed_time], [max_elapsed_time], [query_hash], [query_plan_hash], [total_rows], [last_rows], [min_rows], [max_rows], [Last_grant_kb], [Min_grant_kb], [Max_grant_kb], [Total_grant_kb], [Last_used_grant_kb], [Min_used_grant_kb], [Max_used_grant_kb], [Total_used_grant_kb], [Last_ideal_grant_kb], [Min_ideal_grant_kb], [Max_ideal_grant_kb], [Total_ideal_grant_kb], [Last_dop], [Min_dop], [Max_dop], [Total_dop], [Last_reserved_threads], [Min_reserved_threads], [Max_reserved_threads], [Total_reserved_threads], [Last_used_threads], [Min_used_threads], [Max_used_threads], [Total_used_threads], [Grant2Used_Ratio]\r\n", "\t\t\tFROM #tmp_dm_exec_query_stats;\r\n", "\t\tEND;\r\n", "\t\tUPDATE #dm_exec_query_stats\r\n", "\tSET query_plan = qp.query_plan, \r\n", "\t\t[text] = st.[text],\r\n", "\t\ttext_filtered = SUBSTRING(st.[text], \r\n", "\t\t\t(CASE WHEN qs.statement_start_offset = 0 THEN 0 ELSE qs.statement_start_offset/2 END),\r\n", "\t\t\t(CASE WHEN qs.statement_end_offset = -1 THEN DATALENGTH(st.[text]) ELSE qs.statement_end_offset/2 END - (CASE WHEN qs.statement_start_offset = 0 THEN 0 ELSE qs.statement_start_offset/2 END)))\r\n", "\tFROM #dm_exec_query_stats qs\r\n", "\t\tCROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st\r\n", "\t\tCROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp\r\n", "\t-- Delete own queries\r\n", "\t\tDELETE FROM #dm_exec_query_stats\r\n", "\tWHERE CAST(query_plan AS NVARCHAR(MAX)) LIKE \u0027%Query_Plan_Warnings%\u0027;\r\n", "\t-- Aggregate results\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#qpwarnings\u0027)) \r\n", "\tDROP TABLE #qpwarnings;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#qpwarnings\u0027)) \r\n", "\tCREATE TABLE #qpwarnings\r\n", "\t\t(\r\n", "\t\t\t[Deviation] VARCHAR(50),\r\n", "\t\t\t[Comment] VARCHAR(255),\r\n", "\t\t\tquery_plan XML,\r\n", "\t\t\t[statement] XML\r\n", "\t\t)\r\n", "\t-- Find issues\r\n", "\t\tINSERT INTO #qpwarnings\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT \u0027Scalar_UDFs\u0027AS [Deviation],\r\n", "\t\t\t\t(\u0027[WARNING: Scalar UDF found in a top resource-intensive query, which that may inhibit parallelism]\u0027) AS [Comment],\r\n", "\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027%UserDefinedFunction%\u0027\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Implicit_Conversion_with_IX_Scan\u0027AS [Deviation],\r\n", "\t\t\t\t(\u0027[WARNING: Implicit type conversions found where an Index Scan is present]\u0027) AS Details ,\r\n", "\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027%CONVERT_IMPLICIT%\u0027\r\n", "\t\t\t\tAND CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027%PhysicalOp=\"Index Scan\"%\u0027\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Missing_Index\u0027AS [Deviation],\r\n", "\t\t\t\t(\u0027[WARNING: One of the top resource-intensive queries may be improved by adding an index]\u0027) AS [Comment],\r\n", "\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027%MissingIndexGroup%\u0027\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Cursor\u0027AS [Deviation],\r\n", "\t\t\t\t(\u0027[WARNING: Cursor usage found in a top resource-intensive query. Check if it can be rewritten as a WHILE cycle]\u0027) AS [Comment],\r\n", "\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027% 10\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #qpwarnings\r\n", "\t\t-- Note that currently SpillToTempDb warnings are only found in actual execution plans\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT \u0027Spill_to_TempDb\u0027AS [Deviation],\r\n", "\t\t\t\t\t(\u0027[WARNING: Spill to TempDB found during a HASH or SORT operation]\u0027) AS [Comment],\r\n", "\t\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027%= 5000) OR @sqlmajorver >= 13\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #qpwarnings\r\n", "\t\t-- Note that currently MemoryGrant warnings are only found in actual execution plans\r\n", "\t\t\t\t\t\t\t\t\t\tSELECT \u0027Excessive_Memory_Grant\u0027AS [Deviation],\r\n", "\t\t\t\t\t(\u0027[WARNING: Granted memory was much larger than maximum used memory]\u0027) AS [Comment],\r\n", "\t\t\t\t\tqs.query_plan, (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\tqs.text_filtered, \r\n", "\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement]\r\n", "\t\t\t\tFROM #dm_exec_query_stats qs\r\n", "\t\t\t\tWHERE CAST(qs.query_plan AS NVARCHAR(MAX)) LIKE \u0027% 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Query_Plan_Warnings\u0027 AS [Check], \u0027[WARNING: Top resource-intensive queries issued plan level warnings]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Query_Plan_Warnings\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #qpwarnings) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Query_Plan_Warnings\u0027 AS [Check], [Comment], query_plan, [statement]\r\n", "\t\t\tFROM #qpwarnings;\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #dm_exec_query_stats) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Inefficient_Plans_Reads\u0027 AS [Check], query_plan,\r\n", "\t\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\t\ttext_filtered, \r\n", "\t\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement],\r\n", "\t\t\t\t[execution_count], [total_worker_time]/[execution_count] AS [Avg_Worker_Time],\r\n", "\t\t\t\t[total_physical_reads]/[execution_count] AS [Avg_Physical_Reads],\r\n", "\t\t\t\t[total_logical_reads]/[execution_count] AS [Avg_Logical_Reads],\r\n", "\t\t\t\tCASE WHEN [Total_grant_kb] IS NOT NULL THEN [Total_grant_kb]/[execution_count] ELSE -1 END AS [Avg_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_used_grant_kb] IS NOT NULL THEN [Total_used_grant_kb]/[execution_count] ELSE -1 END AS [Avg_used_grant_kb],\r\n", "\t\t\t\t[Grant2Used_Ratio],\r\n", "\t\t\t\tCASE WHEN [Total_ideal_grant_kb] IS NOT NULL THEN [Total_ideal_grant_kb]/[execution_count] ELSE -1 END AS [Avg_ideal_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_dop] IS NOT NULL THEN [Total_dop]/[execution_count] ELSE -1 END AS [Avg_dop],\r\n", "\t\t\t\tCASE WHEN [Total_reserved_threads] IS NOT NULL THEN [Total_reserved_threads]/[execution_count] ELSE -1 END AS [Avg_reserved_threads],\r\n", "\t\t\t\tCASE WHEN [Total_used_threads] IS NOT NULL THEN [Total_used_threads]/[execution_count] ELSE -1 END AS [Avg_used_threads]\r\n", "\t\t\tFROM #dm_exec_query_stats\r\n", "\t\t\tORDER BY [Avg_Logical_Reads] DESC;\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Inefficient_Plans_CPU\u0027 AS [Check], query_plan,\r\n", "\t\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\t\ttext_filtered, \r\n", "\t\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement],\r\n", "\t\t\t\t[execution_count], [total_worker_time]/[execution_count] AS [Avg_Worker_Time],\r\n", "\t\t\t\t[total_physical_reads]/[execution_count] AS [Avg_Physical_Reads],\r\n", "\t\t\t\t[total_logical_reads]/[execution_count] AS [Avg_Logical_Reads],\r\n", "\t\t\t\tCASE WHEN [Total_grant_kb] IS NOT NULL THEN [Total_grant_kb]/[execution_count] ELSE -1 END AS [Avg_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_used_grant_kb] IS NOT NULL THEN [Total_used_grant_kb]/[execution_count] ELSE -1 END AS [Avg_used_grant_kb],\r\n", "\t\t\t\t[Grant2Used_Ratio],\r\n", "\t\t\t\tCASE WHEN [Total_ideal_grant_kb] IS NOT NULL THEN [Total_ideal_grant_kb]/[execution_count] ELSE -1 END AS [Avg_ideal_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_dop] IS NOT NULL THEN [Total_dop]/[execution_count] ELSE -1 END AS [Avg_dop],\r\n", "\t\t\t\tCASE WHEN [Total_reserved_threads] IS NOT NULL THEN [Total_reserved_threads]/[execution_count] ELSE -1 END AS [Avg_reserved_threads],\r\n", "\t\t\t\tCASE WHEN [Total_used_threads] IS NOT NULL THEN [Total_used_threads]/[execution_count] ELSE -1 END AS [Avg_used_threads]\r\n", "\t\t\tFROM #dm_exec_query_stats\r\n", "\t\t\tORDER BY [Avg_Worker_Time] DESC;\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Inefficient_Memory_Use\u0027 AS [Check], query_plan,\r\n", "\t\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\t\ttext_filtered, \r\n", "\t\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027)\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [statement],\r\n", "\t\t\t\t[execution_count], [total_worker_time]/[execution_count] AS [Avg_Worker_Time],\r\n", "\t\t\t\t[total_physical_reads]/[execution_count] AS [Avg_Physical_Reads],\r\n", "\t\t\t\t[total_logical_reads]/[execution_count] AS [Avg_Logical_Reads],\r\n", "\t\t\t\tCASE WHEN [Total_grant_kb] IS NOT NULL THEN [Total_grant_kb]/[execution_count] ELSE -1 END AS [Avg_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_used_grant_kb] IS NOT NULL THEN [Total_used_grant_kb]/[execution_count] ELSE -1 END AS [Avg_used_grant_kb],\r\n", "\t\t\t\t[Grant2Used_Ratio],\r\n", "\t\t\t\tCASE WHEN [Total_ideal_grant_kb] IS NOT NULL THEN [Total_ideal_grant_kb]/[execution_count] ELSE -1 END AS [Avg_ideal_grant_kb],\r\n", "\t\t\t\tCASE WHEN [Total_dop] IS NOT NULL THEN [Total_dop]/[execution_count] ELSE -1 END AS [Avg_dop],\r\n", "\t\t\t\tCASE WHEN [Total_reserved_threads] IS NOT NULL THEN [Total_reserved_threads]/[execution_count] ELSE -1 END AS [Avg_reserved_threads],\r\n", "\t\t\t\tCASE WHEN [Total_used_threads] IS NOT NULL THEN [Total_used_threads]/[execution_count] ELSE -1 END AS [Avg_used_threads]\r\n", "\t\t\tFROM #dm_exec_query_stats\r\n", "\t\t\tORDER BY Grant2Used_Ratio ASC;\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "b2b04883-5f11-4e67-8768-56614674c11f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Tuning recommendations info subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "545cab04-b457-4895-9ceb-579b0635c0f1" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 13 AND @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Tuning recommendations\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendationsCnt\u0027))\r\n", "\tDROP TABLE #tblTuningRecommendationsCnt;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendationsCnt\u0027))\r\n", "\tCREATE TABLE #tblTuningRecommendationsCnt\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[dbid] int,\r\n", "\t\t\t[HasRecommendations] bit\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendations\u0027))\r\n", "\tDROP TABLE #tblTuningRecommendations;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendations\u0027))\r\n", "\tCREATE TABLE #tblTuningRecommendations\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[query_id] bigint,\r\n", "\t\t\t[reason] NVARCHAR(4000),\r\n", "\t\t\t[score] int,\r\n", "\t\t\t[CurrentState] NVARCHAR(4000),\r\n", "\t\t\t[CurrentStateReason] NVARCHAR(4000),\r\n", "\t\t\t[query_sql_text] NVARCHAR(max),\r\n", "\t\t\t[RegressedPlan] [xml],\r\n", "\t\t\t[SuggestedPlan] [xml],\r\n", "\t\t\t[ImplementationScript] NVARCHAR(100)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] = 2;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], \u0027\u0027\u0027 + REPLACE(@dbid, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [dbid], CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM sys.dm_db_tuning_recommendations;\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblTuningRecommendationsCnt\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Tuning Recommendations subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT COUNT([DBName])\r\n", "\t\tFROM #tblTuningRecommendationsCnt\r\n", "\t\tWHERE [HasRecommendations] = 1)\r\n", "\tBEGIN\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 0\r\n", "\t\tFROM #tblTuningRecommendationsCnt AS trc\r\n", "\t\t\t\tINNER JOIN tempdb.dbo.tmpdbs0 ON tempdb.dbo.tmpdbs0.[dbid] = trc.[dbid]\r\n", "\t\tWHERE [state] <> 0 AND trc.[HasRecommendations] = 1;\r\n", "\t\t\tIF (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", ";WITH CTE_Tuning_Recs AS (SELECT tr.reason, \r\n", "\t\ttr.score, \r\n", "\t\tJSON_VALUE(tr.details,\u0027\u0027$.query_id\u0027\u0027) AS query_id, \r\n", "\t\tJSON_VALUE(tr.details,\u0027\u0027$.regressedPlanId\u0027\u0027) AS regressedPlanId, \r\n", "\t\tJSON_VALUE(tr.details,\u0027\u0027$.recommendedPlanId\u0027\u0027) AS recommendedPlanId,\r\n", "\t\tJSON_VALUE(tr.state,\u0027\u0027$.currentValue\u0027\u0027) AS CurrentState,\r\n", "\t\tJSON_VALUE(tr.state,\u0027\u0027$.reason\u0027\u0027) AS CurrentStateReason,\r\n", "\t\t(CAST(JSON_VALUE(tr.state,\u0027\u0027$.regressedPlanExecutionCount\u0027\u0027) AS int) + CAST(JSON_VALUE(tr.state,\u0027\u0027$.recommendedPlanExecutionCount\u0027\u0027) AS int)) \r\n", "\t\t* (CAST(JSON_VALUE(tr.state,\u0027\u0027$.regressedPlanCpuTimeAverage\u0027\u0027) AS float) - CAST(JSON_VALUE(tr.state,\u0027\u0027$.recommendedPlanCpuTimeAverage\u0027\u0027) AS float))/1000000 AS Estimated_Gain,\r\n", "\t\tCASE WHEN CAST(JSON_VALUE(tr.state,\u0027\u0027$.regressedPlanErrorCount\u0027\u0027) AS int) > CAST(JSON_VALUE(tr.state,\u0027\u0027$.recommendedPlanErrorCount\u0027\u0027) AS int) THEN 1 ELSE 0 END AS Error_Prone,\r\n", "\t\tJSON_VALUE(tr.details,\u0027\u0027$.implementationDetails.script\u0027\u0027) AS ImplementationScript\r\n", "\tFROM sys.dm_db_tuning_recommendations AS tr\r\n", "\t)\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], qsq.query_id, cte.reason, cte.score, cte.CurrentState, cte.CurrentStateReason, qsqt.query_sql_text,\r\n", "\tCAST(rp.query_plan AS XML) AS RegressedPlan, CAST(sp.query_plan AS XML) AS SuggestedPlan, cte.ImplementationScript\r\n", "FROM CTE_Tuning_Recs AS cte\r\n", "INNER JOIN sys.query_store_plan AS rp ON rp.query_id = cte.[query_id] AND rp.plan_id = cte.regressedPlanId\r\n", "INNER JOIN sys.query_store_plan AS sp ON sp.query_id = cte.[query_id] AND sp.plan_id = cte.recommendedPlanId\r\n", "INNER JOIN sys.query_store_query AS qsq\tON qsq.query_id = rp.query_id \r\n", "INNER JOIN sys.query_store_query_text AS qsqt ON qsqt.query_text_id = qsq.query_text_id;\u0027\r\n", "\t\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblTuningRecommendations\r\n", "\t\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Tuning Recommendations List subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND\r\n", "\t\t\tIF (SELECT COUNT(query_id)\r\n", "\t\t\tFROM #tblTuningRecommendations) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Automatic_Tuning_Recommendations\u0027 AS [Check], \u0027[INFORMATION: Found tuning recommendations. If Automatic Tuning is not configured to deploy these recommednations, review manually and decide which ones to deploy]\u0027 AS Comment\r\n", "\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Automatic_Tuning_Recommendations\u0027 AS [Check], DBName AS [Database_Name],\r\n", "\t\t\t\t\t[query_id], [reason], [score], [CurrentState], [CurrentStateReason],\r\n", "\t\t\t\t\t(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\r\n", "\t\t\t\ttr2.query_sql_text,\r\n", "\t\t\t\tNCHAR(0),N\u0027?\u0027),NCHAR(1),N\u0027?\u0027),NCHAR(2),N\u0027?\u0027),NCHAR(3),N\u0027?\u0027),NCHAR(4),N\u0027?\u0027),NCHAR(5),N\u0027?\u0027),NCHAR(6),N\u0027?\u0027),NCHAR(7),N\u0027?\u0027),NCHAR(8),N\u0027?\u0027),NCHAR(11),N\u0027?\u0027),NCHAR(12),N\u0027?\u0027),NCHAR(14),N\u0027?\u0027),NCHAR(15),N\u0027?\u0027),NCHAR(16),N\u0027?\u0027),NCHAR(17),N\u0027?\u0027),NCHAR(18),N\u0027?\u0027),NCHAR(19),N\u0027?\u0027),NCHAR(20),N\u0027?\u0027),NCHAR(21),N\u0027?\u0027),NCHAR(22),N\u0027?\u0027),NCHAR(23),N\u0027?\u0027),NCHAR(24),N\u0027?\u0027),NCHAR(25),N\u0027?\u0027),NCHAR(26),N\u0027?\u0027),NCHAR(27),N\u0027?\u0027),NCHAR(28),N\u0027?\u0027),NCHAR(29),N\u0027?\u0027),NCHAR(30),N\u0027?\u0027),NCHAR(31),N\u0027?\u0027) \r\n", "\t\t\t\tAS [text()]\r\n", "\t\t\t\t\tFROM #tblTuningRecommendations (NOLOCK) AS tr2\r\n", "\t\t\t\t\tWHERE tr2.DBName = tr.DBName AND tr2.query_id = tr.query_id\r\n", "\t\t\t\t\tFOR XML PATH(\u0027\u0027), TYPE) AS [query_sql_text],\r\n", "\t\t\t\t\t[RegressedPlan], [SuggestedPlan], [ImplementationScript]\r\n", "\t\t\t\tFROM #tblTuningRecommendations AS tr;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Automatic_Tuning_Recommendations\u0027 AS [Check], \u0027[INFORMATION: Found tuning recommendations but Query Store does not contain any information on the queries anymore. Skipping]\u0027 AS Comment\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027Automatic_Tuning_Recommendations\u0027 AS [Check], \u0027[NA]\u0027 AS Comment\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "9537a75c-b468-4ed1-a13a-e85f82b23c5f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Declarative Referential Integrity - Untrusted Constraints subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @gen_scripts to ON if you want to generate index related scripts.\r\n", "- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n" ], "metadata": { "azdata_cell_guid": "0706e88c-fdac-4a87-9d82-f71667cf75a8" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Declarative Referential Integrity - Untrusted Constraints\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t/*\r\n", "\tDeclarative Referential Integrity (DRI), meaning “trusting” constraints will allow SQL Server to introduce optimizations that would otherwise not be possible, \r\n", "\tsuch as eliminating JOINs or even not reading any table for particular queries. \r\n", "\tFor example, if a search argument is looking for when a column IS NULL, but there is a NOT NULL constraint in place, the table might not even be accessed from a data read standpoint. \r\n", "\t*/\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDRI\u0027))\r\n", "\tDROP TABLE #tblDRI;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDRI\u0027))\r\n", "\tCREATE TABLE #tblDRI\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[database_name] sysname,\r\n", "\t\t\t[schema_id] int,\r\n", "\t\t\t[schema_name] VARCHAR(100),\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[table_name] VARCHAR(200),\r\n", "\t\t\t[constraint_name] VARCHAR(200),\r\n", "\t\t\t[constraint_type] VARCHAR(10)\r\n", "\t\t\t\tCONSTRAINT PK_DRI PRIMARY KEY CLUSTERED(databaseID, [schema_id], [object_id], [constraint_name])\r\n", "\t\t)\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE \u0027 + QUOTENAME(@dbname) + \u0027\r\n", "SELECT \u0027\u0027\u0027 + CONVERT(VARCHAR(12),@dbid) + \u0027\u0027\u0027 AS [databaseID], \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [database_name], o.[schema_id], t.name AS [schema_name], mst.[object_id], mst.name AS [table_name], FKC.name AS [constraint_name], \u0027\u0027ForeignKey\u0027\u0027 As [constraint_type]\r\n", "FROM sys.foreign_keys FKC (NOLOCK)\r\n", "INNER JOIN sys.objects o (NOLOCK) ON FKC.parent_object_id = o.[object_id]\r\n", "INNER JOIN sys.tables mst (NOLOCK) ON mst.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.schemas t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE o.type = \u0027\u0027U\u0027\u0027 AND FKC.is_not_trusted = 1 AND FKC.is_not_for_replication = 0\r\n", "GROUP BY o.[schema_id], mst.[object_id], FKC.name, t.name, mst.name\r\n", "UNION ALL\r\n", "SELECT \u0027\u0027\u0027 + CONVERT(VARCHAR(12),@dbid) + \u0027\u0027\u0027 AS [databaseID], \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [database_name], t.[schema_id], t.name AS [schema_name], mst.[object_id], mst.name AS [table_name], CC.name AS [constraint_name], \u0027\u0027Check\u0027\u0027 As [constraint_type]\r\n", "FROM sys.check_constraints CC (NOLOCK)\r\n", "INNER JOIN sys.objects o (NOLOCK) ON CC.parent_object_id = o.[object_id]\r\n", "INNER JOIN sys.tables mst (NOLOCK) ON mst.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.schemas t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE o.type = \u0027\u0027U\u0027\u0027 AND CC.is_not_trusted = 1 AND CC.is_not_for_replication = 0 AND CC.is_disabled = 0\r\n", "GROUP BY t.[schema_id], mst.[object_id], CC.name, t.name, mst.name\r\n", "ORDER BY mst.name, [constraint_name];\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblDRI\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Declarative Referential Integrity subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblDRI) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027DRI_UntrustedConstraints\u0027 AS [Check], \u0027[WARNING: Some constraints are not trusted for referential integrity. It is recommended to revise these due to possible performance issues]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027DRI_UntrustedConstraints\u0027 AS [Information], [database_name] AS [Database_Name], constraint_name AS [Constraint_Name],\r\n", "\t\t\t\t[schema_name] AS [Schema_Name], table_name AS [Table_Name], [constraint_type] AS [Constraint_Type]\r\n", "\t\t\tFROM #tblDRI\r\n", "\t\t\tORDER BY [database_name], [schema_name], table_name, [constraint_type];\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @strSQL1 NVARCHAR(4000)\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Trust untrusted Contraints statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tDECLARE cDRI CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [database_name] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \r\n", "\t\t\t\u0027ALTER TABLE \u0027 + QUOTENAME([schema_name]) + \u0027.\u0027 + QUOTENAME(table_name) + CHAR(10) +\r\n", "\t\t\t\u0027WITH CHECK CHECK CONSTRAINT \u0027 + QUOTENAME(constraint_name) + CHAR(10) + \u0027GO\u0027\r\n", "\t\t\t\tFROM #tblDRI\r\n", "\t\t\t\tORDER BY [database_name], [schema_name], table_name, [constraint_type]\r\n", "\t\t\t\tOPEN cDRI\r\n", "\t\t\t\tFETCH NEXT FROM cDRI INTO @strSQL1\r\n", "\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT @strSQL1\r\n", "\t\t\t\t\tFETCH NEXT FROM cDRI INTO @strSQL1\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE cDRI\r\n", "\t\t\t\tDEALLOCATE cDRI\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Ended Trust untrusted Contraints statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Performance_checks\u0027 AS [Category], \u0027DRI_UntrustedConstraints\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n", "\tIF @ptochecks = 1\r\n", "RAISERROR (N\u0027|-Starting Indexes and Statistics Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "230522b5-9c82-415d-962f-c5694a3e977a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Statistics update subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "35379721-3e3b-4d6f-b7f5-1fe2f1693002" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Statistics update\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsUpd\u0027))\r\n", "\tDROP TABLE #tblStatsUpd;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsUpd\u0027))\r\n", "\tCREATE TABLE #tblStatsUpd\r\n", "\t\t(\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\tobjectID int,\r\n", "\t\t\tschemaName VARCHAR(100),\r\n", "\t\t\t[tableName] VARCHAR(250),\r\n", "\t\t\tlast_updated DATETIME,\r\n", "\t\t\t[rows] bigint,\r\n", "\t\t\tmodification_counter bigint,\r\n", "\t\t\t[stats_id] int,\r\n", "\t\t\t[stat_name] VARCHAR(255),\r\n", "\t\t\tauto_created bit,\r\n", "\t\t\tuser_created bit,\r\n", "\t\t\thas_filter bit NULL,\r\n", "\t\t\tfilter_definition NVARCHAR(MAX) NULL,\r\n", "\t\t\tunfiltered_rows bigint,\r\n", "\t\t\tsteps int\r\n", "\t\t)\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid], @dbcmptlevel = [compatibility_level]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tIF ((@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 4000) OR (@sqlmajorver = 11 AND @sqlbuild >= 3000) OR @sqlmajorver > 11) AND @dbcmptlevel > 80\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT DISTINCT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DatabaseName], \u0027\u0027\u0027 + CONVERT(VARCHAR(12),@dbid) + \u0027\u0027\u0027 AS [databaseID], mst.[object_id] AS objectID, t.name AS schemaName, OBJECT_NAME(mst.[object_id]) AS tableName, \r\n", "\tsp.last_updated, sp.[rows], sp.modification_counter, ss.[stats_id], ss.name AS [stat_name], ss.auto_created, ss.user_created, ss.has_filter, ss.filter_definition, sp.unfiltered_rows, sp.steps\r\n", "FROM sys.objects AS o\r\n", "\tINNER JOIN sys.tables AS mst ON mst.[object_id] = o.[object_id]\r\n", "\tINNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "\tINNER JOIN sys.stats AS ss ON ss.[object_id] = mst.[object_id]\r\n", "\tCROSS APPLY sys.dm_db_stats_properties(ss.[object_id], ss.[stats_id]) AS sp\r\n", "WHERE sp.[rows] > 0\r\n", "\tAND\t((sp.[rows] <= 500 AND sp.modification_counter >= 500)\r\n", "\t\tOR (sp.[rows] > 500 AND sp.modification_counter >= (500 + sp.[rows] * 0.20)))\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT DISTINCT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DatabaseName], \u0027\u0027\u0027 + CONVERT(VARCHAR(12),@dbid) + \u0027\u0027\u0027 AS [databaseID], mst.[object_id] AS objectID, t.name AS schemaName, OBJECT_NAME(mst.[object_id]) AS tableName, \r\n", "\tSTATS_DATE(mst.[object_id], ss.stats_id) AS last_updated, SUM(p.[rows]) AS [rows], si.rowmodctr AS modification_counter, ss.stats_id, ss.name AS [stat_name], ss.auto_created, ss.user_created, NULL, NULL, NULL, NULL\r\n", "FROM sys.sysindexes AS si\r\n", "\tINNER JOIN sys.objects AS o ON si.id = o.[object_id]\r\n", "\tINNER JOIN sys.tables AS mst ON mst.[object_id] = o.[object_id]\r\n", "\tINNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "\tINNER JOIN sys.stats AS ss ON ss.[object_id] = o.[object_id]\r\n", "\tINNER JOIN sys.partitions AS p ON p.[object_id] = ss.[object_id]\r\n", "\tLEFT JOIN sys.indexes i ON si.id = i.[object_id] AND si.indid = i.index_id\r\n", "WHERE o.type <> \u0027\u0027S\u0027\u0027 AND i.name IS NOT NULL\r\n", "GROUP BY mst.[object_id], t.name, rowmodctr, ss.stats_id, ss.name, ss.auto_created, ss.user_created\r\n", "HAVING SUM(p.[rows]) > 0\r\n", "\tAND\t((SUM(p.[rows]) <= 500 AND rowmodctr >= 500)\r\n", "\t\tOR (SUM(p.[rows]) > 500 AND rowmodctr >= (500 + SUM(p.[rows]) * 0.20)))\u0027\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblStatsUpd\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Statistics update subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tCREATE INDEX IX_Stats ON #tblStatsUpd([databaseID]);\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblStatsUpd) > 0\r\n", "\tBEGIN\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\t\t\tWHERE is_auto_update_stats_on = 0) > 0 AND (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #tblStatsUpd AS su INNER JOIN master.sys.databases AS sd (NOLOCK) ON su.[databaseID] = sd.[database_id]\r\n", "\t\t\t\tWHERE sd.is_auto_update_stats_on = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_to_update\u0027 AS [Check], \u0027[WARNING: Some databases have Auto_Update_Statistics DISABLED and statistics that might need to be updated]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_to_update\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [tableName] AS [Table_Name], [stats_id] AS [statsID], [stat_name] AS [Statistic_Name],\r\n", "\t\t\t\t\tlast_updated, [rows], modification_counter, CAST((su.modification_counter*1.00/(su.[rows]*1.00))*100.0 AS DECIMAL(18,2)) AS [RowMod_Pct],\r\n", "\t\t\t\t\tCASE WHEN su.auto_created = 0 AND su.user_created = 0 THEN \u0027Index_Statistic\u0027\r\n", "\t\t\t\tWHEN su.auto_created = 0 AND su.user_created = 1 THEN \u0027User_Created\u0027\r\n", "\t\t\t\tWHEN su.auto_created = 1 AND su.user_created = 0 THEN \u0027Auto_Created\u0027\r\n", "\t\t\t\tELSE NULL\r\n", "\t\t\tEND AS [Statistic_Type],\r\n", "\t\t\t\t\tsu.steps, su.has_filter AS [Is_Filtered], su.filter_definition AS [Filter_Definition], su.unfiltered_rows AS [Unfiltered_Rows]\r\n", "\t\t\t\tFROM #tblStatsUpd AS su INNER JOIN master.sys.databases AS sd (NOLOCK) ON su.[databaseID] = sd.[database_id]\r\n", "\t\t\t\tWHERE sd.is_auto_update_stats_on = 0\r\n", "\t\t\t\tORDER BY [DatabaseName], [tableName], [stats_id] DESC\r\n", "\t\t\tEND;\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblStatsUpd AS su INNER JOIN master.sys.databases AS sd (NOLOCK) ON su.[databaseID] = sd.[database_id]\r\n", "\t\t\tWHERE sd.is_auto_update_stats_on = 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_to_update\u0027 AS [Check], \u0027[WARNING: Some databases have Auto_Update_Statistics ENABLED and statistics that might need to be updated]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_to_update\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [tableName] AS [Table_Name], [stats_id] AS [statsID], [stat_name] AS [Statistic_Name],\r\n", "\t\t\t\t\tlast_updated, [rows], modification_counter, CAST((su.modification_counter*1.00/(su.[rows]*1.00))*100.0 AS DECIMAL(18,2)) AS [RowMod_Pct],\r\n", "\t\t\t\t\tCASE WHEN su.auto_created = 0 AND su.user_created = 0 THEN \u0027Index_Statistic\u0027\r\n", "\t\t\t\tWHEN su.auto_created = 0 AND su.user_created = 1 THEN \u0027User_Created\u0027\r\n", "\t\t\t\tWHEN su.auto_created = 1 AND su.user_created = 0 THEN \u0027Auto_Created\u0027\r\n", "\t\t\t\tELSE NULL\r\n", "\t\t\tEND AS [Statistic_Type],\r\n", "\t\t\t\t\tsu.steps, su.has_filter AS [Is_Filtered], su.filter_definition AS [Filter_Definition]\r\n", "\t\t\t\tFROM #tblStatsUpd AS su INNER JOIN master.sys.databases AS sd (NOLOCK) ON su.[databaseID] = sd.[database_id]\r\n", "\t\t\t\tWHERE sd.is_auto_update_stats_on = 1\r\n", "\t\t\t\tORDER BY [DatabaseName], [tableName], [stats_id] DESC\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_to_update\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "a1aefa38-d3c7-4a22-8581-98760cad0e3f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Statistics sampling subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "4a72f2e3-4e3b-485c-b058-ce1a40b28f39" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tIF (@sqlmajorver = 10 AND @sqlminorver = 50 AND @sqlbuild >= 4000) OR (@sqlmajorver = 11 AND @sqlbuild >= 3000) OR @sqlmajorver > 11\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (N\u0027 |-Starting Statistics sampling\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsSamp\u0027))\r\n", "\t\tDROP TABLE #tblStatsSamp;\r\n", "\t\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsSamp\u0027))\r\n", "\t\tCREATE TABLE #tblStatsSamp\r\n", "\t\t\t(\r\n", "\t\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t\t[databaseID] int,\r\n", "\t\t\t\tobjectID int,\r\n", "\t\t\t\tschemaName VARCHAR(100),\r\n", "\t\t\t\t[tableName] VARCHAR(250),\r\n", "\t\t\t\tlast_updated DATETIME,\r\n", "\t\t\t\t[rows] bigint,\r\n", "\t\t\t\tmodification_counter bigint,\r\n", "\t\t\t\t[stats_id] int,\r\n", "\t\t\t\t[stat_name] VARCHAR(255),\r\n", "\t\t\t\trows_sampled bigint,\r\n", "\t\t\t\tauto_created bit,\r\n", "\t\t\t\tuser_created bit,\r\n", "\t\t\t\thas_filter bit NULL,\r\n", "\t\t\t\tfilter_definition NVARCHAR(MAX) NULL,\r\n", "\t\t\t\tunfiltered_rows bigint,\r\n", "\t\t\t\tsteps int\r\n", "\t\t\t)\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 0;\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\t\tIF (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t\t@dbname = [dbname], @dbid = [dbid], @dbcmptlevel = [compatibility_level]\r\n", "\t\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\t\tIF @dbcmptlevel > 80\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT DISTINCT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DatabaseName], \u0027\u0027\u0027 + CONVERT(VARCHAR(12),@dbid) + \u0027\u0027\u0027 AS [databaseID], mst.[object_id] AS objectID, t.name AS schemaName, OBJECT_NAME(mst.[object_id]) AS tableName, \r\n", "\tsp.last_updated, sp.[rows], sp.modification_counter, ss.[stats_id], ss.name AS [stat_name], sp.rows_sampled, ss.auto_created, ss.user_created, ss.has_filter, ss.filter_definition, sp.unfiltered_rows, sp.steps\r\n", "FROM sys.objects AS o\r\n", "\tINNER JOIN sys.tables AS mst ON mst.[object_id] = o.[object_id]\r\n", "\tINNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "\tINNER JOIN sys.stats AS ss ON ss.[object_id] = mst.[object_id]\r\n", "\tCROSS APPLY sys.dm_db_stats_properties(ss.[object_id], ss.[stats_id]) AS sp\r\n", "WHERE sp.[rows] > 0\r\n", "\tAND\tCAST((sp.rows_sampled/(sp.[rows]*1.00))*100.0 AS DECIMAL(5,2)) < 25\u0027\r\n", "\t\t\t\t\t\tBEGIN TRY\r\n", "\t\t\t\t\t\tINSERT INTO #tblStatsSamp\r\n", "\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\t\t\tEND TRY\r\n", "\t\t\t\t\tBEGIN CATCH\r\n", "\t\t\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027Statistics sampling subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\t\t\tEND CATCH\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tSET isdone = 1\r\n", "\t\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND;\r\n", "\t\t\tCREATE INDEX IX_Stats ON #tblStatsSamp([databaseID]);\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblStatsSamp) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_sampling_lt_25pct\u0027 AS [Check], \u0027[WARNING: Some statistics have sampling rates less than 25 pct, consider updating with a larger sample or fullscan if key is not uniformly distributed]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_sampling_lt_25pct\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [tableName] AS [Table_Name], [stats_id] AS [statsID], [stat_name] AS [Statistic_Name],\r\n", "\t\t\t\t\tlast_updated, [rows], rows_sampled, CAST((rows_sampled/([rows]*1.00))*100.0 AS DECIMAL(5,2)) AS [Sample_Pct],\r\n", "\t\t\t\t\tCASE WHEN su.auto_created = 0 AND su.user_created = 0 THEN \u0027Index_Statistic\u0027\r\n", "\t\t\t\t\tWHEN su.auto_created = 0 AND su.user_created = 1 THEN \u0027User_Created\u0027\r\n", "\t\t\t\t\tWHEN su.auto_created = 1 AND su.user_created = 0 THEN \u0027Auto_Created\u0027\r\n", "\t\t\t\t\tELSE NULL\r\n", "\t\t\t\tEND AS [Statistic_Type],\r\n", "\t\t\t\t\tsu.steps, su.has_filter AS [Is_Filtered], su.filter_definition AS [Filter_Definition]\r\n", "\t\t\t\tFROM #tblStatsSamp AS su\r\n", "\t\t\t\tORDER BY [DatabaseName], [tableName], [stats_id] DESC\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Statistics_sampling_lt_25pct\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "257c04ef-37ff-4feb-8fe4-763fb33fbb65", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Hypothetical objects subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @gen_scripts to ON if you want to generate index related scripts.\r\n", "- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexe\r\n" ], "metadata": { "azdata_cell_guid": "528719e3-15e8-4b19-b7b0-e06d6f7322a6" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Hypothetical objects\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHypObj\u0027))\r\n", "\tDROP TABLE #tblHypObj;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHypObj\u0027))\r\n", "\tCREATE TABLE #tblHypObj\r\n", "\t\t(\r\n", "\t\t\t[DBName] sysname,\r\n", "\t\t\t[Schema] VARCHAR(100),\r\n", "\t\t\t[Table] VARCHAR(255),\r\n", "\t\t\t[Object] VARCHAR(255),\r\n", "\t\t\t[Type] VARCHAR(10)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] = 2;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], QUOTENAME(t.name), QUOTENAME(o.[name]), i.name, \u0027\u0027INDEX\u0027\u0027 \r\n", "FROM sys.indexes i \r\n", "INNER JOIN sys.objects o ON o.[object_id] = i.[object_id] \r\n", "INNER JOIN sys.tables AS mst ON mst.[object_id] = i.[object_id]\r\n", "INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE i.is_hypothetical = 1\r\n", "UNION ALL\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], QUOTENAME(t.name), QUOTENAME(o.[name]), s.name, \u0027\u0027STATISTICS\u0027\u0027 \r\n", "FROM sys.stats s \r\n", "INNER JOIN sys.objects o (NOLOCK) ON o.[object_id] = s.[object_id]\r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = s.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE (s.name LIKE \u0027\u0027hind_%\u0027\u0027 OR s.name LIKE \u0027\u0027_dta_stat%\u0027\u0027) AND auto_created = 0\r\n", "AND s.name NOT IN (SELECT name FROM \u0027 + QUOTENAME(@dbname) + \u0027.sys.indexes)\u0027\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tINSERT INTO #tblHypObj\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\r\n", "\t\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027Hypothetical objects subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\t\tSET isdone = 1\r\n", "\t\t\tWHERE [dbid] = @dbid\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tIF (SELECT COUNT([Object])\r\n", "\t\tFROM #tblHypObj) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Hypothetical_objects\u0027 AS [Check], \u0027[WARNING: Some databases have indexes or statistics 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]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Hypothetical_objects\u0027 AS [Information], DBName AS [Database_Name], [Table] AS [Table_Name], [Object] AS [Object_Name], [Type] AS [Object_Type]\r\n", "\t\t\tFROM #tblHypObj\r\n", "\t\t\tORDER BY 2, 3, 5\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @strSQL NVARCHAR(4000)\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Existing Hypothetical objects drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tDECLARE ITW_Stats CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [DBName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM \u0027 + CASE WHEN [Type] = \u0027STATISTICS\u0027 THEN \u0027sys.stats\u0027 ELSE \u0027sys.indexes\u0027 END + \u0027 WHERE name = N\u0027\u0027\u0027+ [Object] + \u0027\u0027\u0027)\u0027 + CHAR(10) +\r\n", "\t\t\tCASE WHEN [Type] = \u0027STATISTICS\u0027 THEN \u0027DROP STATISTICS \u0027 + [Schema] + \u0027.\u0027 + [Table] + \u0027.\u0027 + QUOTENAME([Object]) + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\tELSE \u0027DROP INDEX \u0027 + QUOTENAME([Object]) + \u0027 ON \u0027 + [Schema] + \u0027.\u0027 + [Table] + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10) \r\n", "\t\t\t\tEND\r\n", "\t\t\t\tFROM #tblHypObj\r\n", "\t\t\t\tORDER BY DBName, [Table]\r\n", "\t\t\t\tOPEN ITW_Stats\r\n", "\t\t\t\tFETCH NEXT FROM ITW_Stats INTO @strSQL\r\n", "\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT @strSQL\r\n", "\t\t\t\t\tFETCH NEXT FROM ITW_Stats INTO @strSQL\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE ITW_Stats\r\n", "\t\t\t\tDEALLOCATE ITW_Stats\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Ended Hypothetical objects drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Hypothetical_objects\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "02aa526a-4ea5-4cf2-b02a-cec8b76e172a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Index Health Analysis subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @ixfrag to ON if you want to check for index fragmentation. \r\n", "- Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "- You can set @ixfragscanmode to the scanning mode you prefer. (Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "\t- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n" ], "metadata": { "azdata_cell_guid": "e41feda4-1890-432f-8f85-4bd1e957945c" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ixfrag = 1 AND @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Index Health Analysis check\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE /*@dbid int, */@objectid int, @indexid int, @partition_nr int, @type_desc NVARCHAR(60)\r\n", "\t\tDECLARE @ColumnStoreGetIXSQL NVARCHAR(2000), @ColumnStoreGetIXSQL_Param NVARCHAR(1000), @HasInMem bit\r\n", "\t\tDECLARE /*@sqlcmd NVARCHAR(4000), @params NVARCHAR(500),*/ @schema_name VARCHAR(100), @table_name VARCHAR(300), @KeyCols VARCHAR(4000), @distinctCnt bigint, @OptimBucketCnt bigint\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS\u0027))\r\n", "\tDROP TABLE #tmpIPS;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS\u0027))\r\n", "\tCREATE TABLE #tmpIPS\r\n", "\t\t(\r\n", "\t\t\t[database_id] int,\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[index_id] int,\r\n", "\t\t\t[partition_number] int,\r\n", "\t\t\tfragmentation DECIMAL(18,3),\r\n", "\t\t\t[page_count] bigint,\r\n", "\t\t\t[size_MB] DECIMAL(26,3),\r\n", "\t\t\trecord_count bigint,\r\n", "\t\t\tforwarded_record_count int NULL,\r\n", "\t\t\tCONSTRAINT PK_IPS PRIMARY KEY CLUSTERED(database_id, [object_id], [index_id], [partition_number])\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS_CI\u0027))\r\n", "\tDROP TABLE #tmpIPS_CI;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS_CI\u0027))\r\n", "\tCREATE TABLE #tmpIPS_CI\r\n", "\t\t(\r\n", "\t\t\t[database_id] int,\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[index_id] int,\r\n", "\t\t\t[partition_number] int,\r\n", "\t\t\tfragmentation DECIMAL(18,3),\r\n", "\t\t\t[page_count] bigint,\r\n", "\t\t\t[size_MB] DECIMAL(26,3),\r\n", "\t\t\trecord_count bigint,\r\n", "\t\t\tdelta_store_hobt_id bigint,\r\n", "\t\t\trow_group_id int ,\r\n", "\t\t\t[state] tinyint,\r\n", "\t\t\tstate_description VARCHAR(60),\r\n", "\t\t\tCONSTRAINT PK_IPS_CI PRIMARY KEY CLUSTERED(database_id, [object_id], [index_id], [partition_number], row_group_id)\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXIS\u0027))\r\n", "\tDROP TABLE #tmpXIS;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXIS\u0027))\r\n", "\tCREATE TABLE #tmpXIS\r\n", "\t\t(\r\n", "\t\t\t[database_id] int,\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[xtp_object_id] int,\r\n", "\t\t\t[schema_name] VARCHAR(100) COLLATE database_default,\r\n", "\t\t\t[table_name] VARCHAR(300) COLLATE database_default,\r\n", "\t\t\t[index_id] int,\r\n", "\t\t\t[index_name] VARCHAR(300) COLLATE database_default,\r\n", "\t\t\ttype_desc NVARCHAR(60),\r\n", "\t\t\ttotal_bucket_count bigint,\r\n", "\t\t\tempty_bucket_count bigint,\r\n", "\t\t\tavg_chain_length bigint,\r\n", "\t\t\tmax_chain_length bigint,\r\n", "\t\t\tKeyCols VARCHAR(4000) COLLATE database_default,\r\n", "\t\t\tDistinctCnt bigint NULL,\r\n", "\t\t\tOptimBucketCnt bigint NULL,\r\n", "\t\t\tisdone bit,\r\n", "\t\t\tCONSTRAINT PK_tmpXIS PRIMARY KEY CLUSTERED(database_id, [object_id], [xtp_object_id], [index_id])\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXNCIS\u0027))\r\n", "\tDROP TABLE #tmpXNCIS;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXNCIS\u0027))\r\n", "\tCREATE TABLE #tmpXNCIS\r\n", "\t\t(\r\n", "\t\t\t[database_id] int,\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[xtp_object_id] int,\r\n", "\t\t\t[schema_name] VARCHAR(100) COLLATE database_default,\r\n", "\t\t\t[table_name] VARCHAR(300) COLLATE database_default,\r\n", "\t\t\t[index_id] int,\r\n", "\t\t\t[index_name] VARCHAR(300) COLLATE database_default,\r\n", "\t\t\ttype_desc NVARCHAR(60),\r\n", "\t\t\tdelta_pages bigint,\r\n", "\t\t\tinternal_pages bigint,\r\n", "\t\t\tleaf_pages bigint,\r\n", "\t\t\tpage_update_count bigint,\r\n", "\t\t\tpage_update_retry_count bigint,\r\n", "\t\t\tpage_consolidation_count bigint,\r\n", "\t\t\tpage_consolidation_retry_count bigint,\r\n", "\t\t\tpage_split_count bigint,\r\n", "\t\t\tpage_split_retry_count bigint,\r\n", "\t\t\tkey_split_count bigint,\r\n", "\t\t\tkey_split_retry_count bigint,\r\n", "\t\t\tpage_merge_count bigint,\r\n", "\t\t\tpage_merge_retry_count bigint,\r\n", "\t\t\tkey_merge_count bigint,\r\n", "\t\t\tkey_merge_retry_count bigint,\r\n", "\t\t\tscans_started bigint,\r\n", "\t\t\tscans_retries bigint,\r\n", "\t\t\tCONSTRAINT PK_tmpXNCIS PRIMARY KEY CLUSTERED(database_id, [object_id], [xtp_object_id], [index_id])\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWorking\u0027))\r\n", "\tDROP TABLE #tblWorking;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWorking\u0027))\r\n", "\tCREATE TABLE #tblWorking\r\n", "\t\t(\r\n", "\t\t\tdatabase_id int,\r\n", "\t\t\t[database_name] NVARCHAR(255),\r\n", "\t\t\t[object_id] int,\r\n", "\t\t\t[object_name] NVARCHAR(255),\r\n", "\t\t\tindex_id int,\r\n", "\t\t\tindex_name NVARCHAR(255),\r\n", "\t\t\t[schema_name] NVARCHAR(255),\r\n", "\t\t\tpartition_number int,\r\n", "\t\t\t[type] tinyint,\r\n", "\t\t\ttype_desc NVARCHAR(60),\r\n", "\t\t\tis_done bit\r\n", "\t\t)\r\n", "\t-- type 0 = Heap; 1 = Clustered; 2 = Nonclustered; 3 = XML; 4 = Spatial; 5 = Clustered columnstore; 6 = Nonclustered columnstore; 7 = Nonclustered hash\r\n", "\t\tRAISERROR (N\u0027 |-Populating support table...\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 0;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [state] <> 0 OR [dbid] < 5;\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\tSET isdone = 1\r\n", "\tWHERE [role] = 2 AND secondary_role_allow_connections = 0;\r\n", "\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\tid\r\n", "\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\tWHERE isdone = 0)\r\n", "\tBEGIN\r\n", "\t\t\tWHILE (SELECT COUNT(id)\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\t\tFROM tempdb.dbo.tmpdbs0\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tIF (SELECT CHARINDEX(CHAR(39), @dbname)) > 0\r\n", "\t\t\t\t\tOR (SELECT CHARINDEX(CHAR(45), @dbname)) > 0\r\n", "\t\t\t\t\tOR (SELECT CHARINDEX(CHAR(47), @dbname)) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Skipping Database ID \u0027 + CONVERT(VARCHAR, DB_ID(QUOTENAME(@dbname))) + \u0027 due to potential of SQL Injection\u0027\r\n", "\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT;\r\n", "\t\t\t\tEND\r\n", "\t\t\tELSE\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tSELECT @sqlcmd = \u0027SELECT \u0027 + CONVERT(VARCHAR(10), @dbid) + \u0027, \u0027\u0027\u0027 + DB_NAME(@dbid) + \u0027\u0027\u0027, si.[object_id], mst.[name], si.index_id, si.name, t.name, sp.partition_number, si.[type], si.type_desc, 0\r\n", "FROM [\u0027 + @dbname + \u0027].sys.indexes si\r\n", "INNER JOIN [\u0027 + @dbname + \u0027].sys.partitions sp ON si.[object_id] = sp.[object_id] AND si.index_id = sp.index_id\r\n", "INNER JOIN [\u0027 + @dbname + \u0027].sys.tables AS mst ON mst.[object_id] = si.[object_id]\r\n", "INNER JOIN [\u0027 + @dbname + \u0027].sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE mst.is_ms_shipped = 0 AND \u0027 + CASE WHEN @sqlmajorver <= 11 THEN \u0027 si.[type] <= 2;\u0027 ELSE \u0027 si.[type] IN (0,1,2,5,6,7);\u0027 END\r\n", "\t\t\t\t\tINSERT INTO #tblWorking\r\n", "\t\t\t\t\tEXEC sp_executesql @sqlcmd;\r\n", "\t\t\t\t\tIF @sqlmajorver >= 12\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @sqlcmd = \u0027SELECT @HasInMemOUT = ISNULL((SELECT TOP 1 1 FROM [\u0027 + @dbname + \u0027].sys.filegroups FG where FG.[type] = \u0027\u0027FX\u0027\u0027), 0)\u0027\r\n", "\t\t\t\t\t\tSET @params = N\u0027@HasInMemOUT bit OUTPUT\u0027;\r\n", "\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @HasInMemOUT=@HasInMem OUTPUT\r\n", "\t\t\t\t\t\tIF @HasInMem = 1\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\t\tINSERT INTO #tmpIPS_CI\r\n", "\t\t\t\t\t\t\t\t([database_id], [object_id], [index_id], [partition_number], fragmentation, [page_count], [size_MB], record_count, delta_store_hobt_id, row_group_id, [state], state_description)\r\n", "\t\t\t\t\t\t\tEXECUTE sp_executesql @ColumnStoreGetIXSQL, @ColumnStoreGetIXSQL_Param, @dbid_In = @dbid, @objectid_In = @objectid, @indexid_In = @indexid, @partition_nr_In = @partition_nr;\r\n", "\t\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Gathering sys.dm_db_xtp_hash_index_stats and sys.dm_db_xtp_nonclustered_index_stats data in \u0027 + @dbname + \u0027...\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT;\r\n", "\t\t\t\t\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE [\u0027 + @dbname + \u0027];\r\n", "SELECT \u0027 + CONVERT(NVARCHAR(20), @dbid) + \u0027 AS [database_id], xis.[object_id], xhis.xtp_object_id, t.name, o.name, xis.index_id, si.name, si.type_desc, xhis.total_bucket_count, xhis.empty_bucket_count, xhis.avg_chain_length, xhis.max_chain_length,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] \r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE si.[object_id] = i.[object_id] AND si.index_id = i.index_id AND ic.is_included_column = 0\r\n", "\t\tORDER BY ic.key_ordinal\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyCols, NULL, NULL, 0\r\n", "FROM sys.dm_db_xtp_hash_index_stats AS xhis\r\n", "INNER JOIN sys.dm_db_xtp_index_stats AS xis ON xis.[object_id] = xhis.[object_id] AND xis.[index_id] = xhis.[index_id] \r\n", "INNER JOIN sys.indexes AS si (NOLOCK) ON xis.[object_id] = si.[object_id] AND xis.[index_id] = si.[index_id]\r\n", "INNER JOIN sys.objects AS o (NOLOCK) ON si.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE o.[type] = \u0027\u0027U\u0027\u0027\u0027\r\n", "\t\t\t\t\t\t\tBEGIN TRY\r\n", "\t\t\t\t\t\t\tINSERT INTO #tmpXIS\r\n", "\t\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\t\t\t\tEND TRY\r\n", "\t\t\t\t\t\tBEGIN CATCH\t\t\t\t\t\t\r\n", "\t\t\t\t\t\t\tSET @ErrorMessage = \u0027 |-Error \u0027 + CONVERT(VARCHAR(20),ERROR_NUMBER()) + \u0027 has occurred while analyzing hash indexes. Message: \u0027 + ERROR_MESSAGE() + \u0027 (Line Number: \u0027 + CAST(ERROR_LINE() AS VARCHAR(10)) + \u0027)\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR(@ErrorMessage, 0, 42) WITH NOWAIT;\r\n", "\t\t\t\t\t\tEND CATCH\r\n", "\t\t\t\t\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE [\u0027 + @dbname + \u0027];\r\n", "SELECT DISTINCT \u0027 + CONVERT(NVARCHAR(20), @dbid) + \u0027 AS [database_id],\r\n", "\txis.[object_id], xnis.xtp_object_id, t.name, o.name, xis.index_id, si.name, si.type_desc,\r\n", "\txnis.delta_pages, xnis.internal_pages, xnis.leaf_pages, xnis.page_update_count,\r\n", "\txnis.page_update_retry_count, xnis.page_consolidation_count,\r\n", "\txnis.page_consolidation_retry_count, xnis.page_split_count, xnis.page_split_retry_count,\r\n", "\txnis.key_split_count, xnis.key_split_retry_count, xnis.page_merge_count, xnis.page_merge_retry_count,\r\n", "\txnis.key_merge_count, xnis.key_merge_retry_count,\r\n", "\txis.scans_started, xis.scans_retries\r\n", "FROM sys.dm_db_xtp_nonclustered_index_stats AS xnis (NOLOCK)\r\n", "INNER JOIN sys.dm_db_xtp_index_stats AS xis (NOLOCK) ON xis.[object_id] = xnis.[object_id] AND xis.[index_id] = xnis.[index_id]\r\n", "INNER JOIN sys.indexes AS si (NOLOCK) ON xis.[object_id] = si.[object_id] AND xis.[index_id] = si.[index_id]\r\n", "INNER JOIN sys.objects AS o (NOLOCK) ON si.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE o.[type] = \u0027\u0027U\u0027\u0027\u0027\r\n", "\t\t\t\t\t\t\tBEGIN TRY\r\n", "\t\t\t\t\t\t\tINSERT INTO #tmpXNCIS\r\n", "\t\t\t\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\t\t\t\tEND TRY\r\n", "\t\t\t\t\t\tBEGIN CATCH\t\t\t\t\t\t\r\n", "\t\t\t\t\t\t\tSET @ErrorMessage = \u0027 |-Error \u0027 + CONVERT(VARCHAR(20),ERROR_NUMBER()) + \u0027 has occurred while analyzing nonclustered hash indexes. Message: \u0027 + ERROR_MESSAGE() + \u0027 (Line Number: \u0027 + CAST(ERROR_LINE() AS VARCHAR(10)) + \u0027)\u0027\r\n", "\t\t\t\t\t\t\tRAISERROR(@ErrorMessage, 0, 42) WITH NOWAIT;\r\n", "\t\t\t\t\t\tEND CATCH\r\n", "\t\t\t\t\t\tEND;\r\n", "\t\t\t\t\t/*ELSE\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tSELECT @ErrorMessage = \u0027 |-Skipping \u0027 + DB_NAME(@dbid) + \u0027. No memory optimized filegroup was found...\u0027\r\n", "\t\t\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT;\r\n", "\t\t\t\t\tEND;*/\r\n", "\t\t\t\t\tEND;\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tUPDATE tempdb.dbo.tmpdbs0\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid;\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT TOP 1\r\n", "\t\t\tdatabase_id\r\n", "\t\tFROM #tmpXIS\r\n", "\t\tWHERE isdone = 0)\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (\u0027 |-Gathering additional data on xtp hash indexes...\u0027, 10, 1) WITH NOWAIT;\r\n", "\t\t\tWHILE (SELECT COUNT(database_id)\r\n", "\t\t\tFROM #tmpXIS\r\n", "\t\t\tWHERE isdone = 0) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbid = database_id, @objectid = [object_id], @indexid = [index_id], @schema_name = [schema_name], @table_name = [table_name], @KeyCols = KeyCols\r\n", "\t\t\t\tFROM #tmpXIS\r\n", "\t\t\t\tWHERE isdone = 0\r\n", "\t\t\t\tSELECT @sqlcmd = \u0027USE \u0027 + QUOTENAME(DB_NAME(@dbid)) + \u0027; SELECT @distinctCntOUT = COUNT(*), @OptimBucketCntOUT = POWER(2,CEILING(LOG(CASE WHEN COUNT(*) = 0 THEN 1 ELSE COUNT(*) END)/LOG(2))) FROM (SELECT DISTINCT \u0027 + @KeyCols + \u0027 FROM \u0027 + @schema_name + \u0027.\u0027 + @table_name + \u0027) t1;\u0027\r\n", "\t\t\t\tSET @params = N\u0027@distinctCntOUT bigint OUTPUT, @OptimBucketCntOUT bigint OUTPUT\u0027;\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @distinctCntOUT=@distinctCnt OUTPUT, @OptimBucketCntOUT=@OptimBucketCnt OUTPUT;\r\n", "\t\t\t\tUPDATE #tmpXIS\r\n", "\t\t\tSET DistinctCnt = @distinctCnt, OptimBucketCnt = @OptimBucketCnt, isdone = 1\r\n", "\t\t\tWHERE database_id = @dbid AND [object_id] = @objectid AND [index_id] = @indexid;\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblWorking\r\n", "\t\tWHERE is_done = 0 AND [type] <= 2) > 0\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (\u0027 |-Gathering sys.dm_db_index_physical_stats data...\u0027, 10, 1) WITH NOWAIT;\r\n", "\t\t\tWHILE (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblWorking\r\n", "\t\t\tWHERE is_done = 0 AND [type] <= 2) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbid = database_id, @objectid = [object_id], @indexid = index_id, @partition_nr = partition_number\r\n", "\t\t\t\tFROM #tblWorking\r\n", "\t\t\t\tWHERE is_done = 0 AND [type] <= 2\r\n", "\t\t\t\tINSERT INTO #tmpIPS\r\n", "\t\t\t\tSELECT ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, SUM(ps.avg_fragmentation_in_percent), SUM(ps.page_count),\r\n", "\t\t\t\t\tCAST((SUM(ps.page_count)*8)/1024 AS DECIMAL(26,3)) AS [size_MB], ps.record_count, ps.forwarded_record_count\r\n", "\t\t\t-- for heaps\r\n", "\t\t\t\tFROM sys.dm_db_index_physical_stats(@dbid, @objectid, @indexid , @partition_nr, @ixfragscanmode) AS ps\r\n", "\t\t\t\tWHERE /*ps.index_id > 0 -- ignore heaps\r\n", "\t\t\t\tAND */ps.index_level = 0 -- leaf-level nodes only\r\n", "\t\t\t\t\tAND ps.alloc_unit_type_desc = \u0027IN_ROW_DATA\u0027\r\n", "\t\t\t\tGROUP BY ps.database_id, ps.[object_id], ps.index_id, ps.partition_number, ps.record_count, ps.forwarded_record_count\r\n", "\t\t\t\tOPTION\r\n", "\t\t\t\t(MAXDOP\r\n", "\t\t\t\t2);\r\n", "\t\t\t\tUPDATE #tblWorking\r\n", "\t\t\tSET is_done = 1\r\n", "\t\t\tWHERE database_id = @dbid AND [object_id] = @objectid AND index_id = @indexid AND partition_number = @partition_nr\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblWorking\r\n", "\t\tWHERE is_done = 0 AND type = 5) > 0\r\n", "\tBEGIN\r\n", "\t\t\tRAISERROR (\u0027 |-Gathering sys.column_store_row_groups data...\u0027, 10, 1) WITH NOWAIT;\r\n", "\t\t\tWHILE (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblWorking\r\n", "\t\t\tWHERE is_done = 0 AND type IN (5,6)) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT TOP 1\r\n", "\t\t\t\t\t@dbid = database_id, @objectid = [object_id], @indexid = index_id, @partition_nr = partition_number\r\n", "\t\t\t\tFROM #tblWorking\r\n", "\t\t\t\tWHERE is_done = 0 AND type IN (5,6)\r\n", "\t\t\t\tBEGIN TRY\r\n", "\t\t\t\tSELECT @ColumnStoreGetIXSQL = \u0027SELECT @dbid_In, 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], SUM(ISNULL(rg.size_in_bytes,1)/1024/8) AS [simulated_page_count], CAST(SUM(rg.size_in_bytes)/1024/1024 AS DECIMAL(26,3)) AS [size_MB], rg.total_rows, rg.delta_store_hobt_id, rg.row_group_id, rg.state, rg.state_description\r\n", "FROM [\u0027 + DB_NAME(@dbid) + \u0027].sys.column_store_row_groups rg \r\n", "WHERE rg.object_id = @objectid_In\r\n", "\tAND rg.index_id = @indexid_In\r\n", "\tAND rg.partition_number = @partition_nr_In\r\n", "--AND rg.state = 3 -- Only COMPRESSED row groups\r\n", "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, rg.state_description\r\n", "OPTION (MAXDOP 2)\u0027\r\n", "\t\t\t\tSET @ColumnStoreGetIXSQL_Param = N\u0027@dbid_In int, @objectid_In int, @indexid_In int, @partition_nr_In int\u0027;\r\n", "\t\t\t\tINSERT INTO #tmpIPS_CI\r\n", "\t\t\t\t\t([database_id], [object_id], [index_id], [partition_number], fragmentation, [page_count], [size_MB], record_count, delta_store_hobt_id, row_group_id, [state], state_description)\r\n", "\t\t\t\tEXECUTE sp_executesql @ColumnStoreGetIXSQL, @ColumnStoreGetIXSQL_Param, @dbid_In = @dbid, @objectid_In = @objectid, @indexid_In = @indexid, @partition_nr_In = @partition_nr;\r\n", "\t\t\tEND TRY\r\n", "\t\t\tBEGIN CATCH\t\t\t\t\t\t\r\n", "\t\t\t\tSET @ErrorMessage = \u0027 |-Error \u0027 + CONVERT(VARCHAR(20),ERROR_NUMBER()) + \u0027 has occurred while analyzing columnstore indexes. Message: \u0027 + ERROR_MESSAGE() + \u0027 (Line Number: \u0027 + CAST(ERROR_LINE() AS VARCHAR(10)) + \u0027)\u0027\r\n", "\t\t\t\tRAISERROR(@ErrorMessage, 0, 42) WITH NOWAIT;\r\n", "\t\t\tEND CATCH\r\n", "\t\t\t\tUPDATE #tblWorking\r\n", "\t\t\tSET is_done = 1\r\n", "\t\t\tWHERE database_id = @dbid AND [object_id] = @objectid AND index_id = @indexid AND partition_number = @partition_nr\r\n", "\t\t\tEND\r\n", "\t\tEND;\r\n", "\t-- Check for index fragmentation over 5 pct when index has more than 1 extent allocated, or in CCI, all compressed row groups\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpIPS\r\n", "\t\t\tWHERE fragmentation > 5 AND [page_count] > 8) > 0\r\n", "\t\t\tOR (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpIPS_CI\r\n", "\t\t\tWHERE fragmentation > 5 AND [state] = 3) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Fragmentation\u0027 AS [Check], \u0027[WARNING: Some databases have fragmented indexes. It is recommended to remove fragmentation on a regular basis to maintain performance]\u0027 AS [Deviation]\r\n", "\t\t\t\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Fragmentation\u0027 AS [Check], wk.database_name, wk.[schema_name], wk.[object_name], wk.index_name, wk.type_desc AS index_type, ips.partition_number, ips.fragmentation,\r\n", "\t\t\t\t\tips.page_count, ips.[size_MB], ips.record_count, ips.forwarded_record_count, -- for heaps\r\n", "\t\t\t\t\tNULL AS row_group_id, NULL AS [Comment]\r\n", "\t\t\t\tFROM #tmpIPS ips\r\n", "\t\t\t\t\tINNER JOIN #tblWorking wk ON ips.database_id = wk.database_id AND ips.[object_id] = wk.[object_id] AND ips.index_id = wk.index_id AND ips.partition_number = wk.partition_number\r\n", "\t\t\t\tWHERE ips.fragmentation > 5 AND ips.[page_count] > 8\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Fragmentation\u0027 AS [Check], wk.database_name, wk.[schema_name], wk.[object_name], wk.index_name, wk.type_desc AS index_type, ipsci.partition_number, ipsci.fragmentation,\r\n", "\t\t\t\t\tipsci.page_count, ipsci.[size_MB], ipsci.record_count, NULL AS forwarded_record_count, ipsci.row_group_id,\r\n", "\t\t\t\t\t\u0027Fragmentation for CCI is the ratio of deleted_rows to total_rows; Page count is a simulated value coming from the size in bytes taken by the index]\u0027 AS [Comment]\r\n", "\t\t\t\tFROM #tmpIPS_CI ipsci\r\n", "\t\t\t\t\tINNER JOIN #tblWorking wk ON ipsci.database_id = wk.database_id AND ipsci.[object_id] = wk.[object_id] AND ipsci.index_id = wk.index_id AND ipsci.partition_number = wk.partition_number\r\n", "\t\t\t\tWHERE ipsci.fragmentation > 5 AND ipsci.[state] = 3\r\n", "\t\t\tORDER BY fragmentation DESC, [page_count] ASC\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Fragmentation\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF @sqlmajorver >= 12\r\n", "\tBEGIN\r\n", "\t\t-- For the below values, your mileage may vary. Assuming more than 50 percent empty buckets and an average chain length over 5 requires investigation\r\n", "\t\t-- http://blogs.technet.com/b/dataplatforminsider/archive/2014/01/30/in-memory-oltp-index-troubleshooting-part-ii.aspx\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpXIS\r\n", "\t\t\tWHERE FLOOR((CAST(empty_bucket_count AS FLOAT)/total_bucket_count) * 100) > 50 AND [avg_chain_length] > 5) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_AvgChain_EmptyBuckets\u0027 AS [Check], \u0027[WARNING: Some databases have high avg chain lenght (>5) and high empty buckets count (>50 pct). Verify if there are many rows with duplicate index key values or there is a skew in the key values]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_AvgChain_EmptyBuckets\u0027 AS [Check], DB_NAME([database_id]) AS [database_name], [schema_name], [table_name], [index_name], [type_desc] AS index_type,\r\n", "\t\t\t\t\tDistinctCnt AS [distinct_keys], OptimBucketCnt AS [optimal_bucket_count], total_bucket_count, empty_bucket_count,\r\n", "\t\t\t\t\tFLOOR((CAST(empty_bucket_count AS FLOAT)/total_bucket_count) * 100) AS [empty_bucket_pct], avg_chain_length, max_chain_length\r\n", "\t\t\t\tFROM #tmpXIS\r\n", "\t\t\t\tWHERE FLOOR((CAST(empty_bucket_count AS FLOAT)/total_bucket_count) * 100) > 50 AND [avg_chain_length] > 5\r\n", "\t\t\t\tORDER BY [database_name], [schema_name], table_name, [total_bucket_count] DESC;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_AvgChain_EmptyBuckets\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpXIS\r\n", "\t\t\tWHERE total_bucket_count > DistinctCnt) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooManyBuckets\u0027 AS [Check], \u0027[WARNING: Some databases have a total bucket count larger than the number of distinct rows in the table, which is wasting memory and marginally slowing down full table scans]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooManyBuckets\u0027 AS [Check], DB_NAME([database_id]) AS [database_name], [schema_name], [table_name], [index_name], [type_desc] AS index_type,\r\n", "\t\t\t\t\tDistinctCnt AS [distinct_keys], OptimBucketCnt AS [optimal_bucket_count], total_bucket_count, empty_bucket_count,\r\n", "\t\t\t\t\tFLOOR((CAST(empty_bucket_count AS FLOAT)/total_bucket_count) * 100) AS [empty_bucket_pct], avg_chain_length, max_chain_length\r\n", "\t\t\t\tFROM #tmpXIS\r\n", "\t\t\t\tWHERE total_bucket_count > DistinctCnt\r\n", "\t\t\t\tORDER BY [database_name], [schema_name], table_name, [total_bucket_count] DESC;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooManyBuckets\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpXIS\r\n", "\t\t\tWHERE total_bucket_count < DistinctCnt) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooFewBuckets\u0027 AS [Check], \u0027[WARNING: Some databases have a total bucket count smaller than the number of distinct rows in the table, which leads to chaining records]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooFewBuckets\u0027 AS [Check], DB_NAME([database_id]) AS [database_name], [schema_name], [table_name], [index_name], [type_desc] AS index_type,\r\n", "\t\t\t\t\tDistinctCnt AS [distinct_keys], OptimBucketCnt AS [optimal_bucket_count], total_bucket_count, empty_bucket_count,\r\n", "\t\t\t\t\tFLOOR((CAST(empty_bucket_count AS FLOAT)/total_bucket_count) * 100) AS [empty_bucket_pct], avg_chain_length, max_chain_length\r\n", "\t\t\t\tFROM #tmpXIS\r\n", "\t\t\t\tWHERE total_bucket_count < DistinctCnt\r\n", "\t\t\t\tORDER BY [database_name], [schema_name], table_name, [total_bucket_count] DESC;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_HashIX_Health_TooFewBuckets\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND;\r\n", "\t\t-- For the below values, your mileage may vary. Assuming more than 5 percent retries requires investigation\t.\r\n", "\t\t-- https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-xtp-nonclustered-index-stats-transact-sql\t\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tmpXNCIS\r\n", "\t\t\tWHERE FLOOR((CAST(page_update_retry_count AS FLOAT)/CASE WHEN page_update_count = 0 THEN 1 ELSE page_update_count END) * 100) > 5\r\n", "\t\t\t\tOR FLOOR((CAST(page_consolidation_retry_count AS FLOAT)/CASE WHEN page_consolidation_count = 0 THEN 1 ELSE page_consolidation_count END) * 100) > 5\r\n", "\t\t\t\tOR FLOOR((CAST(page_split_retry_count AS FLOAT)/CASE WHEN page_split_count = 0 THEN 1 ELSE page_split_count END) * 100) > 5\r\n", "\t\t\t\tOR FLOOR((CAST(key_split_retry_count AS FLOAT)/CASE WHEN key_split_count = 0 THEN 1 ELSE key_split_count END) * 100) > 5\r\n", "\t\t\t\tOR FLOOR((CAST(page_merge_retry_count AS FLOAT)/CASE WHEN page_merge_count = 0 THEN 1 ELSE page_merge_count END) * 100) > 5\r\n", "\t\t\t\tOR FLOOR((CAST(key_merge_retry_count AS FLOAT)/CASE WHEN key_merge_count = 0 THEN 1 ELSE key_merge_count END) * 100) > 5\r\n", "\t\t\t) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_RangeIX_Health\u0027 AS [Check], \u0027[WARNING: Some databases have retry count over 5 percent of total, indicating possible concurrency issues]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027XTP_RangeIX_Health\u0027 AS [Category], DB_NAME([database_id]) AS [database_name], [schema_name], [table_name], [index_name], [type_desc] AS index_type,\r\n", "\t\t\t\t\tdelta_pages, internal_pages, leaf_pages,\r\n", "\t\t\t\t\tpage_update_count, page_update_retry_count, FLOOR((CAST(page_update_retry_count AS FLOAT)/CASE WHEN page_update_count = 0 THEN 1 ELSE page_update_count END) * 100) AS [page_update_retry_pct_of_total],\r\n", "\t\t\t\t\tpage_consolidation_count, page_consolidation_retry_count, FLOOR((CAST(page_consolidation_retry_count AS FLOAT)/CASE WHEN page_consolidation_count = 0 THEN 1 ELSE page_consolidation_count END) * 100) AS [page_consolidation_retry_pct_of_total],\r\n", "\t\t\t\t\tpage_split_count, page_split_retry_count, FLOOR((CAST(page_split_retry_count AS FLOAT)/CASE WHEN page_split_count = 0 THEN 1 ELSE page_split_count END) * 100) AS [page_split_retry_pct_of_total],\r\n", "\t\t\t\t\tkey_split_count, key_split_retry_count, FLOOR((CAST(key_split_retry_count AS FLOAT)/CASE WHEN key_split_count = 0 THEN 1 ELSE key_split_count END) * 100) AS [key_split_retry_pct_of_total],\r\n", "\t\t\t\t\tpage_merge_count, page_merge_retry_count, FLOOR((CAST(page_merge_retry_count AS FLOAT)/CASE WHEN page_merge_count = 0 THEN 1 ELSE page_merge_count END) * 100) AS [page_merge_retry_pct_of_total],\r\n", "\t\t\t\t\tkey_merge_count, key_merge_retry_count, FLOOR((CAST(key_merge_retry_count AS FLOAT)/CASE WHEN key_merge_count = 0 THEN 1 ELSE key_merge_count END) * 100) AS [key_merge_retry_pct_of_total]\r\n", "\t\t\t\tFROM #tmpXNCIS\r\n", "\t\t\t\tWHERE FLOOR((CAST(page_update_retry_count AS FLOAT)/CASE WHEN page_update_count = 0 THEN 1 ELSE page_update_count END) * 100) > 5\r\n", "\t\t\t\t\tOR FLOOR((CAST(page_consolidation_retry_count AS FLOAT)/CASE WHEN page_consolidation_count = 0 THEN 1 ELSE page_consolidation_count END) * 100) > 5\r\n", "\t\t\t\t\tOR FLOOR((CAST(page_split_retry_count AS FLOAT)/CASE WHEN page_split_count = 0 THEN 1 ELSE page_split_count END) * 100) > 5\r\n", "\t\t\t\t\tOR FLOOR((CAST(key_split_retry_count AS FLOAT)/CASE WHEN key_split_count = 0 THEN 1 ELSE key_split_count END) * 100) > 5\r\n", "\t\t\t\t\tOR FLOOR((CAST(page_merge_retry_count AS FLOAT)/CASE WHEN page_merge_count = 0 THEN 1 ELSE page_merge_count END) * 100) > 5\r\n", "\t\t\t\t\tOR FLOOR((CAST(key_merge_retry_count AS FLOAT)/CASE WHEN key_merge_count = 0 THEN 1 ELSE key_merge_count END) * 100) > 5\r\n", "\t\t\t\tORDER BY [database_name], [schema_name], table_name, [leaf_pages] DESC;\r\n", "\t\t\tEND;\r\n", "\t\tEND;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027 |- [INFORMATION: \"Index Health Analysis\" check is disabled]\u0027, 10, 1, N\u0027disallow_ixfrag\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "84094a15-fa37-4b73-988f-9bb6570ba64f", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Duplicate or Redundant indexes subsection \r\n", "(clustered, non-clustered, clustered and non-clustered columnstore indexes only)\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "1a67540f-8542-4e3b-a77d-08d2b22280c7" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Duplicate or Redundant indexes\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblIxs1\u0027))\r\n", "\tDROP TABLE tempdb.dbo.tblIxs1;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblIxs1\u0027))\r\n", "\tCREATE TABLE tempdb.dbo.tblIxs1\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[objectID] int,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[indexID] int,\r\n", "\t\t\t[indexName] NVARCHAR(200),\r\n", "\t\t\t[indexType] tinyint,\r\n", "\t\t\tis_primary_key bit,\r\n", "\t\t\t[is_unique_constraint] bit,\r\n", "\t\t\tis_unique bit,\r\n", "\t\t\tis_disabled bit,\r\n", "\t\t\tfill_factor tinyint,\r\n", "\t\t\tis_padded bit,\r\n", "\t\t\thas_filter bit,\r\n", "\t\t\tfilter_definition NVARCHAR(max),\r\n", "\t\t\tKeyCols VARCHAR(4000),\r\n", "\t\t\tKeyColsOrdered VARCHAR(4000),\r\n", "\t\t\tIncludedCols VARCHAR(4000) NULL,\r\n", "\t\t\tIncludedColsOrdered VARCHAR(4000) NULL,\r\n", "\t\t\tAllColsOrdered VARCHAR(4000) NULL,\r\n", "\t\t\t[KeyCols_data_length_bytes] int,\r\n", "\t\t\tCONSTRAINT PK_Ixs PRIMARY KEY CLUSTERED(databaseID, [objectID], [indexID])\r\n", "\t\t);\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblCode\u0027))\r\n", "\tDROP TABLE #tblCode;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblCode\u0027))\r\n", "\tCREATE TABLE #tblCode\r\n", "\t\t(\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[indexName] NVARCHAR(200),\r\n", "\t\t\ttype_desc NVARCHAR(60)\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0;\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 AS Database_ID, N\u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS Database_Name,\r\n", "\tmst.[object_id] AS objectID, t.name AS schemaName, mst.[name] AS objectName, mi.index_id AS indexID, \r\n", "\tmi.[name] AS Index_Name, mi.[type] AS [indexType], mi.is_primary_key, mi.[is_unique_constraint], mi.is_unique, mi.is_disabled,\r\n", "\tmi.fill_factor, mi.is_padded, \u0027 + CASE WHEN @sqlmajorver > 9 THEN \u0027mi.has_filter, mi.filter_definition,\u0027 ELSE \u0027NULL, NULL,\u0027 END + \u0027 \r\n", "\tSUBSTRING(( SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] \r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 0\r\n", "\t\tORDER BY ic.key_ordinal\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyCols,\r\n", "\tSUBSTRING(( SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] \r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 0\r\n", "\t\tORDER BY ac.name\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyColsOrdered,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id]\r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 1\r\n", "\t\tORDER BY ic.key_ordinal\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS IncludedCols,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id]\r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 1\r\n", "\t\tORDER BY ac.name\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS IncludedColsOrdered,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id]\r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id\r\n", "\t\tORDER BY ac.name\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS AllColsOrdered,\r\n", "\t(SELECT SUM(CASE sty.name WHEN \u0027\u0027nvarchar\u0027\u0027 THEN sc.max_length/2 ELSE sc.max_length END) FROM sys.indexes AS i\r\n", "\t\tINNER JOIN sys.tables AS t ON t.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.schemas ss ON ss.[schema_id] = t.[schema_id]\r\n", "\t\tINNER JOIN sys.index_columns AS sic ON sic.object_id = mst.object_id AND sic.index_id = mi.index_id\r\n", "\t\tINNER JOIN sys.columns AS sc ON sc.object_id = t.object_id AND sc.column_id = sic.column_id\r\n", "\t\tINNER JOIN sys.types AS sty ON sc.user_type_id = sty.user_type_id\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND sic.key_ordinal > 0) AS [KeyCols_data_length_bytes]\r\n", "FROM sys.indexes AS mi\r\n", "INNER JOIN sys.tables AS mst ON mst.[object_id] = mi.[object_id]\r\n", "INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE mi.type IN (1,2,5,6) AND mst.is_ms_shipped = 0\r\n", "ORDER BY objectName\r\n", "OPTION (MAXDOP 2);\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO tempdb.dbo.tblIxs1\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Duplicate or Redundant indexes subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid;\r\n", "\t\tEND\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2 ON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\tAND I.[KeyCols] = I2.[KeyCols] AND (I.IncludedCols = I2.IncludedCols OR (I.IncludedCols IS NULL AND I2.IncludedCols IS NULL))\r\n", "\t\t\t\tAND ((I.filter_definition = I2.filter_definition) OR (I.filter_definition IS NULL AND I2.filter_definition IS NULL))) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes\u0027 AS [Check], \u0027[WARNING: Some databases have duplicate indexes. It is recommended to revise the need to maintain all these objects as soon as possible]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name],\r\n", "\t\t\t\tI.[indexID], I.[indexName] AS [Index_Name], I.is_primary_key, I.is_unique_constraint, I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition,\r\n", "\t\t\t\tI.KeyCols, I.IncludedCols, CASE WHEN I.IncludedCols IS NULL THEN I.[KeyCols] ELSE I.[KeyCols] + \u0027,\u0027 + I.IncludedCols END AS [AllColsOrdered]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2\r\n", "\t\t\t\tON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\t\tAND I.[KeyCols] = I2.[KeyCols] AND (I.IncludedCols = I2.IncludedCols OR (I.IncludedCols IS NULL AND I2.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND ((I.filter_definition = I2.filter_definition) OR (I.filter_definition IS NULL AND I2.filter_definition IS NULL))\r\n", "\t\t\tWHERE I.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I2.indexType IN (1,2,5,6)\r\n", "\t\t-- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\tGROUP BY I.[databaseID], I.[DatabaseName], I.[schemaName], I.[objectName], I.[indexID], I.[indexName], I.KeyCols, I.IncludedCols, I.[KeyColsOrdered], I.IncludedColsOrdered, I.is_primary_key, I.is_unique_constraint, I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition\r\n", "\t\t\tORDER BY I.DatabaseName, I.[objectName], I.[indexID]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes_toDrop\u0027 AS [Check], I.[DatabaseName], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name],\r\n", "\t\t\t\tI.[indexID], I.[indexName] AS [Index_Name], I.is_primary_key, I.is_unique_constraint, I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition,\r\n", "\t\t\t\tI.KeyCols, I.IncludedCols, CASE WHEN I.IncludedCols IS NULL THEN I.[KeyCols] ELSE I.[KeyCols] + \u0027,\u0027 + I.IncludedCols END AS [AllColsOrdered]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2\r\n", "\t\t\t\tON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\t\tAND I.[KeyCols] = I2.[KeyCols] AND (I.IncludedCols = I2.IncludedCols OR (I.IncludedCols IS NULL AND I2.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND ((I.filter_definition = I2.filter_definition) OR (I.filter_definition IS NULL AND I2.filter_definition IS NULL))\r\n", "\t\t\tWHERE I.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I2.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I.[indexID] NOT IN (\r\n", "\t\t\t\tSELECT COALESCE((SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND (tI3.is_unique = 1 AND tI3.is_primary_key = 1)\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND (tI3.is_unique = 1 OR tI3.is_primary_key = 1)\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered)\r\n", "\t\t\t\t))\r\n", "\t\t\tGROUP BY I.[databaseID], I.[DatabaseName], I.[schemaName], I.[objectName], I.[indexID], I.[indexName], I.KeyCols, I.IncludedCols, I.[KeyColsOrdered], I.IncludedColsOrdered, I.is_primary_key, I.is_unique_constraint, I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition\r\n", "\t\t\tORDER BY I.DatabaseName, I.[objectName], I.[indexID];\r\n", "\t\t\tDECLARE @strSQL2 NVARCHAR(4000), @DatabaseName sysname, @indexName sysname\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/*\r\n", "NOTE: It is possible that a clustered index (unique or not) is among the duplicate indexes to be dropped, namely if a non-clustered primary key exists on the table.\r\n", "In this case, make the appropriate changes in the clustered index (making it unique and/or primary key in this case), and drop the non-clustered instead.\r\n", "*/\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Existing Duplicate indexes drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tDECLARE Dup_Stats CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + I.[DatabaseName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sys.indexes WHERE name = N\u0027\u0027\u0027+ I.[indexName] + \u0027\u0027\u0027)\u0027 + CHAR(10) +\r\n", "\t\t\t\u0027DROP INDEX \u0027 + QUOTENAME(I.[indexName]) + \u0027 ON \u0027 + QUOTENAME(I.[schemaName]) + \u0027.\u0027 + QUOTENAME(I.[objectName]) + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2\r\n", "\t\t\t\t\tON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\t\t\tAND I.[KeyCols] = I2.[KeyCols] AND (I.IncludedCols = I2.IncludedCols OR (I.IncludedCols IS NULL AND I2.IncludedCols IS NULL))\r\n", "\t\t\t\t\t\tAND ((I.filter_definition = I2.filter_definition) OR (I.filter_definition IS NULL AND I2.filter_definition IS NULL))\r\n", "\t\t\t\tWHERE I.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\t\tAND I2.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\t\tAND I.[indexID] NOT IN (\r\n", "\t\t\t\t\tSELECT COALESCE((SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\t\tAND (tI3.is_unique = 1 AND tI3.is_primary_key = 1)\r\n", "\t\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\t\tAND (tI3.is_unique = 1 OR tI3.is_primary_key = 1)\r\n", "\t\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered)\r\n", "\t\t\t\t\t))\r\n", "\t\t\t\tGROUP BY I.[databaseID], I.[DatabaseName], I.[schemaName], I.[objectName], I.[indexID], I.[indexName], I.KeyCols, I.IncludedCols, I.[KeyColsOrdered], I.IncludedColsOrdered\r\n", "\t\t\t\tORDER BY I.DatabaseName, I.[objectName], I.[indexID];\r\n", "\t\t\t\tOPEN Dup_Stats\r\n", "\t\t\t\tFETCH NEXT FROM Dup_Stats INTO @strSQL2\r\n", "\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT @strSQL2\r\n", "\t\t\t\t\tFETCH NEXT FROM Dup_Stats INTO @strSQL2\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE Dup_Stats\r\n", "\t\t\t\tDEALLOCATE Dup_Stats\r\n", "\t\t\t\tPRINT \u0027--############# Ended Duplicate indexes drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\t\tRAISERROR (N\u0027 |-Starting index search in sql modules...\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tDECLARE Dup_HardCoded CURSOR FAST_FORWARD FOR SELECT I.[DatabaseName], I.[indexName]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2\r\n", "\t\t\t\tON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\t\tAND I.[KeyCols] = I2.[KeyCols] AND (I.IncludedCols = I2.IncludedCols OR (I.IncludedCols IS NULL AND I2.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND ((I.filter_definition = I2.filter_definition) OR (I.filter_definition IS NULL AND I2.filter_definition IS NULL))\r\n", "\t\t\tWHERE I.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I2.indexType IN (1,2,5,6) -- clustered, non-clustered, clustered and non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I.[indexID] NOT IN (\r\n", "\t\t\t\tSELECT COALESCE((SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND (tI3.is_unique = 1 AND tI3.is_primary_key = 1)\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\t\tAND (tI3.is_unique = 1 OR tI3.is_primary_key = 1)\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered),\r\n", "\t\t\t\t(SELECT MIN(tI3.[indexID]) FROM tempdb.dbo.tblIxs1 tI3\r\n", "\t\t\t\tWHERE tI3.[databaseID] = I.[databaseID] AND tI3.[objectID] = I.[objectID] \r\n", "\t\t\t\t\tAND tI3.[KeyCols] = I.[KeyCols] AND (tI3.IncludedCols = I.IncludedCols OR (tI3.IncludedCols IS NULL AND I.IncludedCols IS NULL))\r\n", "\t\t\t\tGROUP BY tI3.[objectID], tI3.KeyCols, tI3.IncludedCols, tI3.[KeyColsOrdered], tI3.IncludedColsOrdered)\r\n", "\t\t\t\t))\r\n", "\t\t\tGROUP BY I.[databaseID], I.[DatabaseName], I.[schemaName], I.[objectName], I.[indexID], I.[indexName], I.KeyCols, I.IncludedCols, I.[KeyColsOrdered], I.IncludedColsOrdered\r\n", "\t\t\tORDER BY I.DatabaseName, I.[objectName], I.[indexID];\r\n", "\t\t\tOPEN Dup_HardCoded\r\n", "\t\t\tFETCH NEXT FROM Dup_HardCoded INTO @DatabaseName,@indexName\r\n", "\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @sqlcmd = N\u0027USE [\u0027 + @DatabaseName + N\u0027];\r\n", "SELECT \u0027\u0027\u0027 + @DatabaseName + N\u0027\u0027\u0027 AS [database], ss.name AS [schemaName], so.name AS [objectName], \u0027\u0027\u0027 + @indexName + N\u0027\u0027\u0027 AS indexName, so.type_desc\r\n", "FROM sys.sql_modules sm\r\n", "INNER JOIN sys.objects so ON sm.[object_id] = so.[object_id]\r\n", "INNER JOIN sys.schemas ss ON ss.[schema_id] = so.[schema_id]\r\n", "WHERE sm.[definition] LIKE \u0027\u0027%\u0027 + @indexName + N\u0027%\u0027\u0027\u0027\r\n", "\t\t\t\tINSERT INTO #tblCode\r\n", "\t\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\t\t\tFETCH NEXT FROM Dup_HardCoded INTO @DatabaseName,@indexName\r\n", "\t\t\tEND\r\n", "\t\t\tCLOSE Dup_HardCoded\r\n", "\t\t\tDEALLOCATE Dup_HardCoded\r\n", "\t\t\tRAISERROR (N\u0027 |-Ended index search in sql modules\u0027, 10, 1) WITH NOWAIT\r\n", "\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM #tblCode) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes_HardCoded\u0027 AS [Check], \u0027[WARNING: Some sql modules have references to these duplicate indexes. Fix these references to be able to drop duplicate indexes]\u0027 AS [Deviation]\r\n", "\t\t\t\tSELECT [DatabaseName], [schemaName], [objectName] AS [referedIn_objectName], indexName AS [referenced_indexName], type_desc AS [refered_objectType]\r\n", "\t\t\t\tFROM #tblCode\r\n", "\t\t\t\tORDER BY [DatabaseName], [objectName]\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes_HardCoded\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Duplicate_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2 ON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\tAND (I.[KeyCols] <> I2.[KeyCols] OR I.IncludedCols <> I2.IncludedCols)\r\n", "\t\t\t\tAND (((I.[KeyColsOrdered] <> I2.[KeyColsOrdered] OR I.IncludedColsOrdered <> I2.IncludedColsOrdered)\r\n", "\t\t\t\tAND ((CASE WHEN I.IncludedColsOrdered IS NULL THEN I.[KeyColsOrdered] ELSE I.[KeyColsOrdered] + \u0027,\u0027 + I.IncludedColsOrdered END) = (CASE WHEN I2.IncludedColsOrdered IS NULL THEN I2.[KeyColsOrdered] ELSE I2.[KeyColsOrdered] + \u0027,\u0027 + I2.IncludedColsOrdered END)\r\n", "\t\t\t\tOR I.[AllColsOrdered] = I2.[AllColsOrdered]))\r\n", "\t\t\t\tOR (I.[KeyColsOrdered] <> I2.[KeyColsOrdered] AND I.IncludedColsOrdered = I2.IncludedColsOrdered)\r\n", "\t\t\t\tOR (I.[KeyColsOrdered] = I2.[KeyColsOrdered] AND I.IncludedColsOrdered <> I2.IncludedColsOrdered)\r\n", "\t\t\t\tOR ((I.[AllColsOrdered] = I2.[AllColsOrdered] AND I.filter_definition IS NULL AND I2.filter_definition IS NOT NULL) OR (I.[AllColsOrdered] = I2.[AllColsOrdered] AND I.filter_definition IS NOT NULL AND I2.filter_definition IS NULL)))\r\n", "\t\t\t\tAND I.indexID NOT IN (SELECT I3.[indexID]\r\n", "\t\t\t\tFROM tempdb.dbo.tblIxs1 I3 INNER JOIN tempdb.dbo.tblIxs1 I4\r\n", "\t\t\t\t\tON I3.[databaseID] = I4.[databaseID] AND I3.[objectID] = I4.[objectID] AND I3.[indexID] <> I4.[indexID]\r\n", "\t\t\t\t\t\tAND I3.[KeyCols] = I4.[KeyCols] AND (I3.IncludedCols = I4.IncludedCols OR (I3.IncludedCols IS NULL AND I4.IncludedCols IS NULL))\r\n", "\t\t\t\tWHERE I3.[databaseID] = I.[databaseID] AND I3.[objectID] = I.[objectID]\r\n", "\t\t\t\tGROUP BY I3.[indexID])\r\n", "\t\tWHERE I.indexType IN (1,2,5,6) -- 1 = clustered, 2 = non-clustered, 5 = clustered and 7 = non-clustered columnstore indexes only\r\n", "\t\t\tAND I2.indexType IN (1,2,5,6) -- 1 = clustered, 2 = non-clustered, 5 = clustered and 7 = non-clustered columnstore indexes only\r\n", "\t\t\tAND I.is_unique_constraint = 0 -- no unique constraints\r\n", "\t\t\tAND I2.is_unique_constraint = 0-- no unique constraints\r\n", "\t\t) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Redundant_Indexes\u0027 AS [Check], \u0027[WARNING: Some databases have possibly redundant indexes. It is recommended to revise the need to maintain all these objects as soon as possible]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Redundant_Indexes\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name],\r\n", "\t\t\t\tI.[indexID], I.[indexName] AS [Index_Name], I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition,\r\n", "\t\t\t\tI.KeyCols, I.IncludedCols, CASE WHEN I.IncludedColsOrdered IS NULL THEN I.[KeyColsOrdered] ELSE I.[KeyColsOrdered] + \u0027,\u0027 + I.IncludedColsOrdered END AS [KeyInclColsOrdered]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I INNER JOIN tempdb.dbo.tblIxs1 I2\r\n", "\t\t\t\tON I.[databaseID] = I2.[databaseID] AND I.[objectID] = I2.[objectID] AND I.[indexID] <> I2.[indexID]\r\n", "\t\t\t\t\tAND (((I.[KeyColsOrdered] <> I2.[KeyColsOrdered] OR I.IncludedColsOrdered <> I2.IncludedColsOrdered)\r\n", "\t\t\t\t\tAND ((CASE WHEN I.IncludedColsOrdered IS NULL THEN I.[KeyColsOrdered] ELSE I.[KeyColsOrdered] + \u0027,\u0027 + I.IncludedColsOrdered END) = (CASE WHEN I2.IncludedColsOrdered IS NULL THEN I2.[KeyColsOrdered] ELSE I2.[KeyColsOrdered] + \u0027,\u0027 + I2.IncludedColsOrdered END)\r\n", "\t\t\t\t\tOR I.[AllColsOrdered] = I2.[AllColsOrdered]))\r\n", "\t\t\t\t\tOR (I.[KeyColsOrdered] <> I2.[KeyColsOrdered] AND I.IncludedColsOrdered = I2.IncludedColsOrdered)\r\n", "\t\t\t\t\tOR (I.[KeyColsOrdered] = I2.[KeyColsOrdered] AND I.IncludedColsOrdered <> I2.IncludedColsOrdered)\r\n", "\t\t\t\t\tOR ((I.[AllColsOrdered] = I2.[AllColsOrdered] AND I.filter_definition IS NULL AND I2.filter_definition IS NOT NULL) OR (I.[AllColsOrdered] = I2.[AllColsOrdered] AND I.filter_definition IS NOT NULL AND I2.filter_definition IS NULL)))\r\n", "\t\t\t\t\tAND I.indexID NOT IN (SELECT I3.[indexID]\r\n", "\t\t\t\t\tFROM tempdb.dbo.tblIxs1 I3 INNER JOIN tempdb.dbo.tblIxs1 I4\r\n", "\t\t\t\t\t\tON I3.[databaseID] = I4.[databaseID] AND I3.[objectID] = I4.[objectID] AND I3.[indexID] <> I4.[indexID]\r\n", "\t\t\t\t\t\t\tAND I3.[KeyCols] = I4.[KeyCols] AND (I3.IncludedCols = I4.IncludedCols OR (I3.IncludedCols IS NULL AND I4.IncludedCols IS NULL))\r\n", "\t\t\t\t\tWHERE I3.[databaseID] = I.[databaseID] AND I3.[objectID] = I.[objectID]\r\n", "\t\t\t\t\tGROUP BY I3.[indexID])\r\n", "\t\t\tWHERE I.indexType IN (1,2,5,6) -- 1 = clustered, 2 = non-clustered, 5 = clustered and 7 = non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I2.indexType IN (1,2,5,6) -- 1 = clustered, 2 = non-clustered, 5 = clustered and 7 = non-clustered columnstore indexes only\r\n", "\t\t\t\tAND I.is_unique_constraint = 0 -- no unique constraints\r\n", "\t\t\t\tAND I2.is_unique_constraint = 0\r\n", "\t\t-- no unique constraints\r\n", "\t\t\tGROUP BY I.[DatabaseName], I.[schemaName], I.[objectName], I.[indexID], I.[indexName], I.KeyCols, I.IncludedCols, I.[KeyColsOrdered], I.IncludedColsOrdered, I.is_unique, I.fill_factor, I.is_padded, I.has_filter, I.filter_definition\r\n", "\t\t\tORDER BY I.DatabaseName, I.[objectName], I.[KeyColsOrdered], I.IncludedColsOrdered, I.[indexID]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Redundant_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "f603f1ce-e7c0-4856-873b-93686136f503", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Unused and rarely used indexes subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @gen_scripts to ON if you want to generate index related scripts.\r\n", "- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexe\r\n" ], "metadata": { "azdata_cell_guid": "7a4596b7-f865-4c75-ac80-5a07e848ad08" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Unused and rarely used indexes\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs2\u0027))\r\n", "\tDROP TABLE #tblIxs2;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs2\u0027))\r\n", "\tCREATE TABLE #tblIxs2\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[objectID] int,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[indexID] int,\r\n", "\t\t\t[indexName] NVARCHAR(200),\r\n", "\t\t\t[Hits] bigint NULL,\r\n", "\t\t\t[Reads_Ratio] DECIMAL(5,2),\r\n", "\t\t\t[Writes_Ratio] DECIMAL(5,2),\r\n", "\t\t\tuser_updates bigint,\r\n", "\t\t\tlast_user_seek DATETIME NULL,\r\n", "\t\t\tlast_user_scan DATETIME NULL,\r\n", "\t\t\tlast_user_lookup DATETIME NULL,\r\n", "\t\t\tlast_user_update DATETIME NULL,\r\n", "\t\t\tis_unique bit,\r\n", "\t\t\t[type] tinyint,\r\n", "\t\t\tis_primary_key bit,\r\n", "\t\t\tis_unique_constraint bit,\r\n", "\t\t\tis_disabled bit,\r\n", "\t\t\tCONSTRAINT PK_Ixs2 PRIMARY KEY CLUSTERED(databaseID, [objectID], [indexID])\r\n", "\t\t)\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0;\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 AS Database_ID, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS Database_Name,\r\n", "\tmst.[object_id] AS objectID, t.name AS schemaName, mst.[name] AS objectName, si.index_id AS indexID, si.[name] AS Index_Name,\r\n", "\t(s.user_seeks + s.user_scans + s.user_lookups) AS [Hits],\r\n", "\tRTRIM(CONVERT(NVARCHAR(10),CAST(CASE WHEN (s.user_seeks + s.user_scans + s.user_lookups) = 0 THEN 0 ELSE CONVERT(REAL, (s.user_seeks + s.user_scans + s.user_lookups)) * 100 /\r\n", "\t\tCASE (s.user_seeks + s.user_scans + s.user_lookups + s.user_updates) WHEN 0 THEN 1 ELSE CONVERT(REAL, (s.user_seeks + s.user_scans + s.user_lookups + s.user_updates)) END END AS DECIMAL(18,2)))) AS [Reads_Ratio],\r\n", "\tRTRIM(CONVERT(NVARCHAR(10),CAST(CASE WHEN s.user_updates = 0 THEN 0 ELSE CONVERT(REAL, s.user_updates) * 100 /\r\n", "\t\tCASE (s.user_seeks + s.user_scans + s.user_lookups + s.user_updates) WHEN 0 THEN 1 ELSE CONVERT(REAL, (s.user_seeks + s.user_scans + s.user_lookups + s.user_updates)) END END AS DECIMAL(18,2)))) AS [Writes_Ratio],\r\n", "\ts.user_updates,\r\n", "\tMAX(s.last_user_seek) AS last_user_seek,\r\n", "\tMAX(s.last_user_scan) AS last_user_scan,\r\n", "\tMAX(s.last_user_lookup) AS last_user_lookup,\r\n", "\tMAX(s.last_user_update) AS last_user_update,\r\n", "\tsi.is_unique, si.[type], si.is_primary_key, si.is_unique_constraint, si.is_disabled\t\r\n", "FROM sys.indexes AS si (NOLOCK)\r\n", "INNER JOIN sys.objects AS o (NOLOCK) ON si.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = si.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "INNER JOIN sys.dm_db_index_usage_stats AS s (NOLOCK) ON s.database_id = \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 \r\n", "\tAND s.object_id = si.object_id AND s.index_id = si.index_id\r\n", "WHERE mst.is_ms_shipped = 0\r\n", "--AND OBJECTPROPERTY(o.object_id,\u0027\u0027IsUserTable\u0027\u0027) = 1 -- sys.tables only returns type U\r\n", "\tAND si.type IN (2,6) \t\t-- non-clustered and non-clustered columnstore indexes only\r\n", "\tAND si.is_primary_key = 0 \t-- no primary keys\r\n", "\tAND si.is_unique_constraint = 0-- no unique constraints\r\n", "--AND si.is_unique = 0 \t\t-- no alternate keys\r\n", "GROUP BY mst.[object_id], t.[name], mst.[name], si.index_id, si.[name], s.user_seeks, s.user_scans, s.user_lookups, s.user_updates, si.is_unique,\r\n", "\tsi.[type], si.is_primary_key, si.is_unique_constraint, si.is_disabled\r\n", "ORDER BY objectName\t\r\n", "OPTION (MAXDOP 2);\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs2\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Unused and rarely used indexes subsection - Error raised in TRY block 1 in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0;\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 AS Database_ID, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS Database_Name, \r\n", "\tsi.[object_id] AS objectID, t.name AS schemaName, OBJECT_NAME(si.[object_id], \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027) AS objectName, si.index_id AS indexID, \r\n", "\tsi.[name] AS Index_Name, 0, 0, 0, 0, NULL, NULL, NULL, NULL,\r\n", "\tsi.is_unique, si.[type], si.is_primary_key, si.is_unique_constraint, si.is_disabled\r\n", "FROM sys.indexes AS si (NOLOCK)\r\n", "INNER JOIN sys.objects AS so (NOLOCK) ON si.object_id = so.object_id \r\n", "INNER JOIN sys.tables AS mst (NOLOCK) ON mst.[object_id] = si.[object_id]\r\n", "INNER JOIN sys.schemas AS t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE OBJECTPROPERTY(so.object_id,\u0027\u0027IsUserTable\u0027\u0027) = 1\r\n", "\tAND mst.is_ms_shipped = 0\r\n", "\tAND si.index_id NOT IN (SELECT s.index_id\r\n", "\t\tFROM sys.dm_db_index_usage_stats s\r\n", "\t\tWHERE s.object_id = si.object_id \r\n", "\t\t\tAND si.index_id = s.index_id \r\n", "\t\t\tAND database_id = \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027)\r\n", "\tAND si.name IS NOT NULL\r\n", "\tAND si.type IN (2,6) \t\t-- non-clustered and non-clustered columnstore indexes only\r\n", "\tAND si.is_primary_key = 0 \t-- no primary keys\r\n", "\tAND si.is_unique_constraint = 0-- no unique constraints\r\n", "--AND si.is_unique = 0 \t\t-- no alternate keys\r\n", "\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs2\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Unused and rarely used indexes subsection - Error raised in TRY block 2 in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs2\r\n", "\t\tWHERE [Hits] = 0 /*AND is_disabled = 0*/) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Unused_Indexes\u0027 AS [Check], \u0027[WARNING: Some databases have unused indexes. It is recommended to revise the need to maintain all these objects as soon as possible]\u0027 AS [Deviation]\r\n", "\t\t\t\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Unused_Indexes_With_Updates\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [indexID], [indexName] AS [Index_Name], is_unique,\r\n", "\t\t\t\t\t[Hits], CONVERT(NVARCHAR,[Reads_Ratio]) COLLATE database_default + \u0027/\u0027 + CONVERT(NVARCHAR,[Writes_Ratio]) COLLATE database_default AS [R/W_Ratio],\r\n", "\t\t\t\t\tuser_updates, last_user_update\r\n", "\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\tWHERE [Hits] = 0 AND last_user_update > 0\r\n", "\t\t\tUNION ALL\r\n", "\t\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Unused_Indexes_No_Updates\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [indexID], [indexName] AS [Index_Name], is_unique,\r\n", "\t\t\t\t\t[Hits], CONVERT(NVARCHAR,[Reads_Ratio]) COLLATE database_default + \u0027/\u0027 + CONVERT(NVARCHAR,[Writes_Ratio]) COLLATE database_default AS [R/W_Ratio],\r\n", "\t\t\t\t\tuser_updates, last_user_update\r\n", "\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\tWHERE [Hits] = 0 AND (last_user_update = 0 OR last_user_update IS NULL)\r\n", "\t\t\tORDER BY [Information], [Database_Name], [Table_Name], [R/W_Ratio] DESC;\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @strSQL3 NVARCHAR(4000)\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\tWHERE [Hits] = 0 AND last_user_update > 0) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT CHAR(10) + \u0027--############# Existing unused indexes with updates drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\t\tDECLARE Un_Stats CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [DatabaseName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sys.indexes WHERE name = N\u0027\u0027\u0027+ [indexName] + \u0027\u0027\u0027)\u0027 + CHAR(10) +\r\n", "\t\t\t\t\u0027DROP INDEX \u0027 + QUOTENAME([indexName]) + \u0027 ON \u0027 + QUOTENAME([schemaName]) + \u0027.\u0027 + QUOTENAME([objectName]) + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\t\tWHERE [Hits] = 0 AND last_user_update > 0\r\n", "\t\t\t\t\tORDER BY [DatabaseName], [objectName], [Reads_Ratio] DESC;\r\n", "\t\t\t\t\tOPEN Un_Stats\r\n", "\t\t\t\t\tFETCH NEXT FROM Un_Stats INTO @strSQL3\r\n", "\t\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tPRINT @strSQL3\r\n", "\t\t\t\t\t\tFETCH NEXT FROM Un_Stats INTO @strSQL3\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tCLOSE Un_Stats\r\n", "\t\t\t\t\tDEALLOCATE Un_Stats\r\n", "\t\t\t\t\tPRINT CHAR(10) + \u0027--############# Ended unused indexes with updates drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\tWHERE [Hits] = 0 AND (last_user_update = 0 OR last_user_update IS NULL)) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT CHAR(10) + \u0027--############# Existing unused indexes with no updates drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\t\tDECLARE Un_Stats CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [DatabaseName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sys.indexes WHERE name = N\u0027\u0027\u0027+ [indexName] + \u0027\u0027\u0027)\u0027 + CHAR(10) +\r\n", "\t\t\t\t\u0027DROP INDEX \u0027 + QUOTENAME([indexName]) + \u0027 ON \u0027 + QUOTENAME([schemaName]) + \u0027.\u0027 + QUOTENAME([objectName]) + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\t\tWHERE [Hits] = 0 AND (last_user_update = 0 OR last_user_update IS NULL)\r\n", "\t\t\t\t\tORDER BY [DatabaseName], [objectName], [Reads_Ratio] DESC;\r\n", "\t\t\t\t\tOPEN Un_Stats\r\n", "\t\t\t\t\tFETCH NEXT FROM Un_Stats INTO @strSQL3\r\n", "\t\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tPRINT @strSQL3\r\n", "\t\t\t\t\t\tFETCH NEXT FROM Un_Stats INTO @strSQL3\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tCLOSE Un_Stats\r\n", "\t\t\t\t\tDEALLOCATE Un_Stats\r\n", "\t\t\t\t\tPRINT CHAR(10) + \u0027--############# Ended unused indexes with no updates drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tEND\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Unused_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs2\r\n", "\t\tWHERE [Hits] > 0 AND [Reads_Ratio] < 5 AND type IN (1,2,5,6) AND is_primary_key = 0 AND is_unique_constraint = 0 /*AND is_disabled = 0*/) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Rarely_Used_Indexes\u0027 AS [Check], \u0027[WARNING: Some databases have rarely used indexes. It is recommended to revise the need to maintain all these objects as soon as possible]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Rarely_Used_Indexes\u0027 AS [Information], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [indexID], [indexName] AS [Index_Name], is_unique,\r\n", "\t\t\t\t[Hits], CONVERT(NVARCHAR,[Reads_Ratio]) COLLATE database_default + \u0027/\u0027 + CONVERT(NVARCHAR,[Writes_Ratio]) COLLATE database_default AS [R/W_Ratio],\r\n", "\t\t\t\tuser_updates, last_user_seek, last_user_scan, last_user_lookup, last_user_update\r\n", "\t\t\tFROM #tblIxs2\r\n", "\t\t\tWHERE [Hits] > 0 AND [Reads_Ratio] < 5\r\n", "\t\t\tORDER BY [DatabaseName], [objectName], [Reads_Ratio] DESC\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @strSQL4 NVARCHAR(4000)\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# Existing rarely used indexes drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tDECLARE curRarUsed CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [DatabaseName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sys.indexes WHERE name = N\u0027\u0027\u0027+ [indexName] + \u0027\u0027\u0027)\u0027 + CHAR(10) +\r\n", "\t\t\t\u0027DROP INDEX \u0027 + QUOTENAME([indexName]) + \u0027 ON \u0027 + QUOTENAME([schemaName]) + \u0027.\u0027 + QUOTENAME([objectName]) + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\tFROM #tblIxs2\r\n", "\t\t\t\tWHERE [Hits] > 0 AND [Reads_Ratio] < 5\r\n", "\t\t\t\tORDER BY [DatabaseName], [objectName], [Reads_Ratio] DESC\r\n", "\t\t\t\tOPEN curRarUsed\r\n", "\t\t\t\tFETCH NEXT FROM curRarUsed INTO @strSQL4\r\n", "\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT @strSQL4\r\n", "\t\t\t\t\tFETCH NEXT FROM curRarUsed INTO @strSQL4\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE curRarUsed\r\n", "\t\t\t\tDEALLOCATE curRarUsed\r\n", "\t\t\t\tPRINT \u0027--############# Ended rarely used indexes drop statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Rarely_Used_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "3ab990c9-c279-4bbb-bc8b-d3367b3a238a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Indexes with large keys (> 900 bytes for clustered index; 1700 bytes for nonclustered index) subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "94eea29a-2fc7-4f68-b4b7-11ccdc6fa039" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Indexes with large keys\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1\r\n", "\t\tWHERE ([KeyCols_data_length_bytes] > 900 AND @sqlmajorver < 13)\r\n", "\t\t\tOR ([KeyCols_data_length_bytes] > 900 AND indexType IN (1,5) AND @sqlmajorver >= 13)\r\n", "\t\t\tOR ([KeyCols_data_length_bytes] > 1700 AND indexType IN (2,6) AND @sqlmajorver >= 13)) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Large_Index_Key\u0027 AS [Check],\r\n", "\t\t\t\tCASE WHEN @sqlmajorver < 13 THEN \u0027[WARNING: Some indexes have keys larger than 900 bytes. It is recommended to revise these]\u0027 \r\n", "\t\t\t\tELSE \u0027[WARNING: Some indexes have keys larger than allowed (900 bytes for clustered index; 1700 bytes for nonclustered index). It is recommended to revise these]\u0027 END AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Large_Index_Key\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name], I.[indexID], I.[indexName] AS [Index_Name], I.indexType, I.KeyCols, [KeyCols_data_length_bytes]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I\r\n", "\t\t\tWHERE ([KeyCols_data_length_bytes] > 900 AND @sqlmajorver < 13)\r\n", "\t\t\t\tOR ([KeyCols_data_length_bytes] > 900 AND indexType IN (1,5) AND @sqlmajorver >= 13)\r\n", "\t\t\t\tOR ([KeyCols_data_length_bytes] > 1700 AND indexType IN (2,6) AND @sqlmajorver >= 13)\r\n", "\t\t\tORDER BY I.[DatabaseName], I.schemaName, I.[objectName], I.[indexID]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Large_Index_Key\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "578ace92-7407-410a-8cb5-cce72d0af65a", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Indexes with fill factor < 80 pct subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "7a88f257-3dc7-4b13-8097-e88d618dc2e9" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Indexes with fill factor < 80 pct\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1\r\n", "\t\tWHERE [fill_factor] BETWEEN 1 AND 79) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Low_Fill_Factor\u0027 AS [Check], \u0027[WARNING: Some indexes have a fill factor lower than 80 percent. Revise the need to maintain such a low value]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Low_Fill_Factor\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name], I.[indexID], I.[indexName] AS [Index_Name],\r\n", "\t\t\t\t[fill_factor], I.KeyCols, I.IncludedCols, CASE WHEN I.IncludedCols IS NULL THEN I.[KeyCols] ELSE I.[KeyCols] + \u0027,\u0027 + I.IncludedCols END AS [AllColsOrdered]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I\r\n", "\t\t\tWHERE [fill_factor] BETWEEN 1 AND 79\r\n", "\t\t\tORDER BY I.[DatabaseName], I.schemaName, I.[objectName], I.[indexID]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Low_Fill_Factor\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "8f7b6863-6dd2-4feb-b25f-8e01924fe960", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Disabled indexes subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "72522c51-f158-426c-b132-c9fe9644f478" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Disabled indexes\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1\r\n", "\t\tWHERE [is_disabled] = 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Disabled_IXs\u0027 AS [Check], \u0027[WARNING: Some indexes are disabled. Revise the need to maintain these]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Disabled_IXs\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name], I.[indexID], I.[indexName] AS [Index_Name],\r\n", "\t\t\t\tCASE WHEN [indexType] = 1 THEN \u0027Clustered\u0027 \r\n", "\t\t\tWHEN [indexType] = 2 THEN \u0027Non-clustered\u0027\r\n", "\t\t\tWHEN [indexType] = 3 THEN \u0027Clustered columnstore\u0027\r\n", "\t\t\tELSE \u0027Non-clustered columnstore\u0027 END AS [Index_Type],\r\n", "\t\t\t\tI.KeyCols, I.IncludedCols, CASE WHEN I.IncludedCols IS NULL THEN I.[KeyCols] ELSE I.[KeyCols] + \u0027,\u0027 + I.IncludedCols END AS [AllColsOrdered]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I\r\n", "\t\t\tWHERE [is_disabled] = 1\r\n", "\t\t\tORDER BY I.[DatabaseName], I.schemaName, I.[objectName], I.[indexID]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Disabled_IXs\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "100730b2-dfd2-4792-b2cd-63adc8984469", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Non-unique clustered indexes subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "f5116cb4-f7c0-49c5-a82c-946fed664baf" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Non-unique clustered indexes\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM tempdb.dbo.tblIxs1\r\n", "\t\tWHERE [is_unique] = 0 AND indexID = 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027NonUnique_CIXs\u0027 AS [Check], \u0027[WARNING: Some clustered indexes are non-unique. Revise the need to have non-unique clustering keys to which a uniquefier is added]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027NonUnique_CIXs\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name], I.[indexID], I.[indexName] AS [Index_Name], I.[KeyCols]\r\n", "\t\t\tFROM tempdb.dbo.tblIxs1 I\r\n", "\t\t\tWHERE [is_unique] = 0 AND indexID = 1\r\n", "\t\t\tORDER BY I.[DatabaseName], I.schemaName, I.[objectName]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027NonUnique_CIXs\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "bf187e6d-9fed-4290-9546-7e8f51574bf9", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Clustered Indexes with GUIDs in key subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "11b28d25-0008-4e16-a6cd-ac8cd7a86ffb" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Clustered Indexes with GUIDs in key\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs6\u0027))\r\n", "\tDROP TABLE #tblIxs6;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs6\u0027))\r\n", "\tCREATE TABLE #tblIxs6\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[objectID] int,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[indexID] int,\r\n", "\t\t\t[indexName] NVARCHAR(200),\r\n", "\t\t\t[indexType] tinyint,\r\n", "\t\t\t[is_unique_constraint] bit,\r\n", "\t\t\tis_unique bit,\r\n", "\t\t\tis_disabled bit,\r\n", "\t\t\tfill_factor tinyint,\r\n", "\t\t\tis_padded bit,\r\n", "\t\t\tKeyCols NVARCHAR(4000),\r\n", "\t\t\tKeyColsOrdered NVARCHAR(4000),\r\n", "\t\t\tKey_has_GUID int,\r\n", "\t\t\tCONSTRAINT PK_Ixs3 PRIMARY KEY CLUSTERED(databaseID, [objectID], [indexID])\r\n", "\t\t);\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0;\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 AS Database_ID, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS Database_Name,\r\n", "\tmst.[object_id] AS objectID, t.name AS schemaName, mst.[name] AS objectName, mi.index_id AS indexID, \r\n", "\tmi.[name] AS Index_Name, mi.[type] AS [indexType], mi.[is_unique_constraint], mi.is_unique, mi.is_disabled,\r\n", "\tmi.fill_factor, mi.is_padded,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] \r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 0\r\n", "\t\tORDER BY ic.key_ordinal\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyCols,\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + ac.name FROM sys.tables AS st\r\n", "\t\tINNER JOIN sys.indexes AS i ON st.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.index_columns AS ic ON i.[object_id] = ic.[object_id] AND i.[index_id] = ic.[index_id] \r\n", "\t\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND ic.is_included_column = 0\r\n", "\t\tORDER BY ac.name\r\n", "\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyColsOrdered,\r\n", "\t(SELECT COUNT(sty.name) FROM sys.indexes AS i\r\n", "\t\tINNER JOIN sys.tables AS t ON t.[object_id] = i.[object_id]\r\n", "\t\tINNER JOIN sys.schemas ss ON ss.[schema_id] = t.[schema_id]\r\n", "\t\tINNER JOIN sys.index_columns AS sic ON sic.object_id = mst.object_id AND sic.index_id = mi.index_id\r\n", "\t\tINNER JOIN sys.columns AS sc ON sc.object_id = t.object_id AND sc.column_id = sic.column_id\r\n", "\t\tINNER JOIN sys.types AS sty ON sc.user_type_id = sty.user_type_id\r\n", "\t\tWHERE mi.[object_id] = i.[object_id] AND mi.index_id = i.index_id AND sic.is_included_column = 0 AND sty.name = \u0027\u0027uniqueidentifier\u0027\u0027) AS [Key_has_GUID]\r\n", "FROM sys.indexes AS mi\r\n", "INNER JOIN sys.tables AS mst ON mst.[object_id] = mi.[object_id]\r\n", "INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE mi.type = 1 AND mi.is_unique_constraint = 0\r\n", "\tAND mst.is_ms_shipped = 0\r\n", "--AND OBJECTPROPERTY(o.object_id,\u0027\u0027IsUserTable\u0027\u0027) = 1 -- sys.tables only returns type U\r\n", "ORDER BY objectName\r\n", "OPTION (MAXDOP 2);\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs6\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Clustered Indexes with GUIDs in key subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs6\r\n", "\t\tWHERE [Key_has_GUID] > 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Key_GUID\u0027 AS [Check], \u0027[WARNING: Some clustered indexes have GUIDs in the key. It is recommended to revise these]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Key_GUID\u0027 AS [Information], I.[DatabaseName] AS [Database_Name], I.schemaName AS [Schema_Name], I.[objectName] AS [Table_Name], I.[indexID], I.[indexName] AS [Index_Name], I.KeyCols\r\n", "\t\t\tFROM #tblIxs6 I\r\n", "\t\t\tWHERE [Key_has_GUID] > 0\r\n", "\t\t\tORDER BY I.[DatabaseName], I.schemaName, I.[objectName], I.[indexID]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Index_Key_GUID\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "6a8c206d-ea06-498a-a6ad-743a9f9a9023", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Foreign Keys with no Index subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "64b950c5-7f09-4316-a6eb-f45ab42674de" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Foreign Keys with no Index\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFK\u0027))\r\n", "\tDROP TABLE #tblFK;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFK\u0027))\r\n", "\tCREATE TABLE #tblFK\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[constraint_name] NVARCHAR(200),\r\n", "\t\t\t[parent_schema_name] NVARCHAR(100),\r\n", "\t\t\t[parent_table_name] NVARCHAR(200),\r\n", "\t\t\tparent_columns NVARCHAR(4000),\r\n", "\t\t\t[referenced_schema] NVARCHAR(100),\r\n", "\t\t\t[referenced_table_name] NVARCHAR(200),\r\n", "\t\t\treferenced_columns NVARCHAR(4000),\r\n", "\t\t\tCONSTRAINT PK_FK PRIMARY KEY CLUSTERED(databaseID, [constraint_name], [parent_schema_name])\r\n", "\t\t)\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n", "USE \u0027 + QUOTENAME(@dbname) + \u0027\r\n", ";WITH cteFK AS (\r\n", "SELECT t.name AS [parent_schema_name],\r\n", "\tOBJECT_NAME(FKC.parent_object_id) [parent_table_name],\r\n", "\tOBJECT_NAME(constraint_object_id) AS [constraint_name],\r\n", "\tt2.name AS [referenced_schema],\r\n", "\tOBJECT_NAME(referenced_object_id) AS [referenced_table_name],\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + RTRIM(COL_NAME(k.parent_object_id,parent_column_id)) AS [data()]\r\n", "\t\tFROM sys.foreign_key_columns k (NOLOCK)\r\n", "\t\tINNER JOIN sys.foreign_keys (NOLOCK) ON k.constraint_object_id = [object_id]\r\n", "\t\t\tAND k.constraint_object_id = FKC.constraint_object_id\r\n", "\t\tORDER BY constraint_column_id\r\n", "\t\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS [parent_columns],\r\n", "\tSUBSTRING((SELECT \u0027\u0027,\u0027\u0027 + RTRIM(COL_NAME(k.referenced_object_id,referenced_column_id)) AS [data()]\r\n", "\t\tFROM sys.foreign_key_columns k (NOLOCK)\r\n", "\t\tINNER JOIN sys.foreign_keys (NOLOCK) ON k.constraint_object_id = [object_id]\r\n", "\t\t\tAND k.constraint_object_id = FKC.constraint_object_id\r\n", "\t\tORDER BY constraint_column_id\r\n", "\t\tFOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS [referenced_columns]\r\n", "FROM sys.foreign_key_columns FKC (NOLOCK)\r\n", "INNER JOIN sys.objects o (NOLOCK) ON FKC.parent_object_id = o.[object_id]\r\n", "INNER JOIN sys.tables mst (NOLOCK) ON mst.[object_id] = o.[object_id]\r\n", "INNER JOIN sys.schemas t (NOLOCK) ON t.[schema_id] = mst.[schema_id]\r\n", "INNER JOIN sys.objects so (NOLOCK) ON FKC.referenced_object_id = so.[object_id]\r\n", "INNER JOIN sys.tables AS mst2 (NOLOCK) ON mst2.[object_id] = so.[object_id]\r\n", "INNER JOIN sys.schemas AS t2 (NOLOCK) ON t2.[schema_id] = mst2.[schema_id]\r\n", "WHERE o.type = \u0027\u0027U\u0027\u0027 AND so.type = \u0027\u0027U\u0027\u0027\r\n", "GROUP BY o.[schema_id],so.[schema_id],FKC.parent_object_id,constraint_object_id,referenced_object_id,t.name,t2.name\r\n", "),\r\n", "cteIndexCols AS (\r\n", "SELECT t.name AS schemaName,\r\n", "OBJECT_NAME(mst.[object_id]) AS objectName,\r\n", "SUBSTRING(( SELECT \u0027\u0027,\u0027\u0027 + RTRIM(ac.name) FROM sys.tables AS st\r\n", "\tINNER JOIN sys.indexes AS mi ON st.[object_id] = mi.[object_id]\r\n", "\tINNER JOIN sys.index_columns AS ic ON mi.[object_id] = ic.[object_id] AND mi.[index_id] = ic.[index_id] \r\n", "\tINNER JOIN sys.all_columns AS ac ON st.[object_id] = ac.[object_id] AND ic.[column_id] = ac.[column_id]\r\n", "\tWHERE i.[object_id] = mi.[object_id] AND i.index_id = mi.index_id AND ic.is_included_column = 0\r\n", "\tORDER BY ac.column_id\r\n", "FOR XML PATH(\u0027\u0027\u0027\u0027)), 2, 8000) AS KeyCols\r\n", "FROM sys.indexes AS i\r\n", "INNER JOIN sys.tables AS mst ON mst.[object_id] = i.[object_id]\r\n", "INNER JOIN sys.schemas AS t ON t.[schema_id] = mst.[schema_id]\r\n", "WHERE i.[type] IN (1,2,5,6) AND i.is_unique_constraint = 0\r\n", "\tAND mst.is_ms_shipped = 0\r\n", ")\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027 AS Database_ID, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS Database_Name, fk.constraint_name AS constraintName,\r\n", "\tfk.parent_schema_name AS schemaName, fk.parent_table_name AS tableName,\r\n", "\tREPLACE(fk.parent_columns,\u0027\u0027 ,\u0027\u0027,\u0027\u0027,\u0027\u0027) AS parentColumns, fk.referenced_schema AS referencedSchemaName,\r\n", "\tfk.referenced_table_name AS referencedTableName, REPLACE(fk.referenced_columns,\u0027\u0027 ,\u0027\u0027,\u0027\u0027,\u0027\u0027) AS referencedColumns\r\n", "FROM cteFK fk\r\n", "WHERE NOT EXISTS (SELECT 1 FROM cteIndexCols ict \r\n", "\t\t\t\t\tWHERE fk.parent_schema_name = ict.schemaName\r\n", "\t\t\t\t\t\tAND fk.parent_table_name = ict.objectName \r\n", "\t\t\t\t\t\tAND REPLACE(fk.parent_columns,\u0027\u0027 ,\u0027\u0027,\u0027\u0027,\u0027\u0027) = ict.KeyCols);\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblFK\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Foreign Keys with no Index subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblFK) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027FK_no_Index\u0027 AS [Check], \u0027[WARNING: Some Foreign Key constraints are not supported by an Index. It is recommended to revise these]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027FK_no_Index\u0027 AS [Information], FK.[DatabaseName] AS [Database_Name], constraint_name AS [Constraint_Name],\r\n", "\t\t\t\tFK.parent_schema_name AS [Schema_Name], FK.parent_table_name AS [Table_Name],\r\n", "\t\t\t\tFK.parent_columns AS parentColumns, FK.referenced_schema AS Referenced_Schema_Name,\r\n", "\t\t\t\tFK.referenced_table_name AS Referenced_Table_Name, FK.referenced_columns AS referencedColumns\r\n", "\t\t\tFROM #tblFK FK\r\n", "\t\t\tORDER BY [DatabaseName], parent_schema_name, parent_table_name, referenced_schema, referenced_table_name\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tDECLARE @strSQL5 NVARCHAR(4000)\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027--############# FK index creation statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\tDECLARE curFKs CURSOR FAST_FORWARD FOR SELECT \u0027USE \u0027 + [DatabaseName] + CHAR(10) + \u0027GO\u0027 + CHAR(10) +\r\n", "\t\t\t\u0027CREATE INDEX IX_\u0027 + REPLACE(constraint_name,\u0027 \u0027,\u0027_\u0027) + \u0027 ON \u0027 + QUOTENAME(parent_schema_name) + \u0027.\u0027 + QUOTENAME(parent_table_name) + \u0027 ([\u0027 + REPLACE(REPLACE(parent_columns,\u0027,\u0027,\u0027],[\u0027),\u0027]]\u0027,\u0027]\u0027) + \u0027]);\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\tFROM #tblFK\r\n", "\t\t\t\tORDER BY [DatabaseName], parent_schema_name, parent_table_name, referenced_schema, referenced_table_name\r\n", "\t\t\t\tOPEN curFKs\r\n", "\t\t\t\tFETCH NEXT FROM curFKs INTO @strSQL5\r\n", "\t\t\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT @strSQL5\r\n", "\t\t\t\t\tFETCH NEXT FROM curFKs INTO @strSQL5\r\n", "\t\t\t\tEND\r\n", "\t\t\t\tCLOSE curFKs\r\n", "\t\t\t\tDEALLOCATE curFKs\r\n", "\t\t\t\tPRINT \u0027--############# Ended FK index creation statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027FK_no_Index\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "bed593ef-8dc1-40fb-9958-58204d76636d", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Indexing per Table subsection\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n" ], "metadata": { "azdata_cell_guid": "b000ce5a-80c9-4de3-943c-db2f3362a19e" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Indexing per Table\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs3\u0027))\r\n", "\tDROP TABLE #tblIxs3;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs3\u0027))\r\n", "\tCREATE TABLE #tblIxs3\r\n", "\t\t(\r\n", "\t\t\t[Operation] tinyint,\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[Rows] BIGINT\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs4\u0027))\r\n", "\tDROP TABLE #tblIxs4;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs4\u0027))\r\n", "\tCREATE TABLE #tblIxs4\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[CntCols] int,\r\n", "\t\t\t[CntIxs] int\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs5\u0027))\r\n", "\tDROP TABLE #tblIxs5;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs5\u0027))\r\n", "\tCREATE TABLE #tblIxs5\r\n", "\t\t(\r\n", "\t\t\t[databaseID] int,\r\n", "\t\t\t[DatabaseName] sysname,\r\n", "\t\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t\t[objectName] NVARCHAR(200),\r\n", "\t\t\t[indexName] NVARCHAR(200),\r\n", "\t\t\t[indexLocation] NVARCHAR(200)\r\n", "\t\t)\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 0\r\n", "\t\tWHILE (SELECT COUNT(id)\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT TOP 1\r\n", "\t\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\t\tWHERE isdone = 0\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT 1 AS [Check], \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027,\t\r\n", "s.name, t.name, SUM(p.rows)\r\n", "FROM sys.indexes AS si (NOLOCK)\r\n", "INNER JOIN sys.tables AS t (NOLOCK) ON si.[object_id] = t.[object_id]\r\n", "INNER JOIN sys.schemas AS s (NOLOCK) ON s.[schema_id] = t.[schema_id]\r\n", "INNER JOIN sys.partitions AS p (NOLOCK) ON si.[object_id]=p.[object_id] and si.[index_id]=p.[index_id]\r\n", "WHERE si.is_hypothetical = 0\r\n", "GROUP BY si.[object_id], t.name, s.name\r\n", "HAVING COUNT(si.index_id) = 1 AND MAX(si.index_id) = 0\r\n", "UNION ALL\r\n", "SELECT 2 AS [Check], \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027,\t\r\n", "s.name, t.name, SUM(p.rows)\r\n", "FROM sys.indexes AS si (NOLOCK) \r\n", "INNER JOIN sys.tables AS t (NOLOCK) ON si.[object_id] = t.[object_id]\r\n", "INNER JOIN sys.schemas AS s (NOLOCK) ON s.[schema_id] = t.[schema_id]\r\n", "INNER JOIN sys.partitions AS p (NOLOCK) ON si.[object_id]=p.[object_id] and si.[index_id]=p.[index_id]\r\n", "WHERE si.is_hypothetical = 0\r\n", "GROUP BY t.name, s.name\r\n", "HAVING COUNT(si.index_id) > 1 AND MIN(si.index_id) = 0;\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs3\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Indexing per Table subsection - Error raised in TRY block 1 in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027,\ts.name, t.name, COUNT(c.column_id), \r\n", "(SELECT COUNT(si.index_id) FROM sys.tables AS t2 INNER JOIN sys.indexes AS si ON si.[object_id] = t2.[object_id]\r\n", "\tWHERE si.index_id > 0 AND si.[object_id] = t.[object_id] AND si.is_hypothetical = 0\r\n", "\tGROUP BY si.[object_id])\r\n", "FROM sys.tables AS t (NOLOCK)\r\n", "INNER JOIN sys.columns AS c (NOLOCK) ON t.[object_id] = c.[object_id] \r\n", "INNER JOIN sys.schemas AS s (NOLOCK) ON s.[schema_id] = t.[schema_id]\r\n", "GROUP BY s.name, t.name, t.[object_id];\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs4\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Indexing per Table subsection - Error raised in TRY block 2 in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT DISTINCT \u0027 + CONVERT(VARCHAR(8), @dbid) + \u0027, \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027, s.name, t.name, i.name, ds.name\r\n", "FROM sys.tables AS t (NOLOCK)\r\n", "INNER JOIN sys.indexes AS i (NOLOCK) ON t.[object_id] = i.[object_id] \r\n", "INNER JOIN sys.data_spaces AS ds (NOLOCK) ON ds.data_space_id = i.data_space_id\r\n", "INNER JOIN sys.schemas AS s (NOLOCK) ON s.[schema_id] = t.[schema_id]\r\n", "WHERE t.[type] = \u0027\u0027U\u0027\u0027\r\n", "\tAND i.[type] IN (1,2)\r\n", "\tAND i.is_hypothetical = 0\r\n", "-- Get partitioned tables\r\n", "\tAND t.name IN (SELECT ob.name \r\n", "\t\t\tFROM sys.tables AS ob (NOLOCK)\r\n", "\t\t\tINNER JOIN sys.indexes AS ind (NOLOCK) ON ind.[object_id] = ob.[object_id] \r\n", "\t\t\tINNER JOIN sys.data_spaces AS sds (NOLOCK) ON sds.data_space_id = ind.data_space_id\r\n", "\t\t\tWHERE sds.[type] = \u0027\u0027PS\u0027\u0027\r\n", "\t\t\tGROUP BY ob.name)\r\n", "\tAND ds.[type] <> \u0027\u0027PS\u0027\u0027;\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #tblIxs5\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Indexing per Table subsection - Error raised in TRY block 3 in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\t\tSET isdone = 1\r\n", "\t\tWHERE [dbid] = @dbid\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs3\r\n", "\t\tWHERE [Operation] = 1) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_Indexes\u0027 AS [Check], \u0027[WARNING: Some tables do not have indexes]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_Indexes\u0027 AS [Check], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [Rows] AS [Row_Count]\r\n", "\t\t\tFROM #tblIxs3\r\n", "\t\t\tWHERE [Operation] = 1\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs3\r\n", "\t\tWHERE [Operation] = 2) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_CL_Index\u0027 AS [Check], \u0027[WARNING: Some tables do not have a clustered index, but have non-clustered index(es)]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_CL_Index\u0027 AS [Check], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [Rows] AS [Row_Count]\r\n", "\t\t\tFROM #tblIxs3\r\n", "\t\t\tWHERE [Operation] = 2\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_no_CL_Index\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs4\r\n", "\t\tWHERE [CntCols] < [CntIxs]) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_more_Indexes_than_Cols\u0027 AS [Check], \u0027[WARNING: Some tables have more indexes than columns]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_more_Indexes_than_Cols\u0027 AS [Check], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [CntCols] AS [Cnt_Columns], [CntIxs] AS [Cnt_Indexes]\r\n", "\t\t\tFROM #tblIxs4\r\n", "\t\t\tWHERE [CntCols] < [CntIxs]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_more_Indexes_than_Cols\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #tblIxs5) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_partition_misaligned_Indexes\u0027 AS [Check], \u0027[WARNING: Some partitioned tables have indexes that are not aligned with the partition schema]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_partition_misaligned_Indexes\u0027 AS [Check], [DatabaseName] AS [Database_Name], schemaName AS [Schema_Name], [objectName] AS [Table_Name], [indexName] AS [Index_Name], [indexLocation]\r\n", "\t\t\tFROM #tblIxs5\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Tables_with_partition_misaligned_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "8938e603-1e11-48df-81a4-f72c106e80af", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Missing Indexes subsection\r\n", "- Outputs only potentially most relevant, based in scoring method - use at you own discretion)\r\n", "- You can set @ptochecks to OFF in this block if you want to skip more performance tuning and optimization oriented checks.\r\n", "- You can set @gen_scripts to ON if you want to generate index related scripts.\r\n", "- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexe\r\n" ], "metadata": { "azdata_cell_guid": "0a9afecb-846b-4d56-a02b-15e0a5831b3b" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @ptochecks = 1\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Missing Indexes\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tDECLARE @IC NVARCHAR(4000), @ICWI NVARCHAR(4000), @editionCheck bit\r\n", "\t\t/* Refer to https://docs.microsoft.com/sql/t-sql/functions/serverproperty-transact-sql */\r\n", "\t\tIF (SELECT SERVERPROPERTY(\u0027EditionID\u0027)) IN (1804890536, 1872460670, 610778273, -2117995310)\t\r\n", "\tSET @editionCheck = 1 -- supports enterprise only features\r\n", "\tELSE\t\r\n", "\tSET @editionCheck = 0;\r\n", "\t-- does not support enterprise only features\r\n", "\t-- Create the helper functions\r\n", "\t\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_allcols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_allcols\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; EXEC(\u0027\u0027\r\n", "CREATE FUNCTION dbo.fn_createindex_allcols (@ix_handle int)\r\n", "RETURNS NVARCHAR(max)\r\n", "AS\r\n", "BEGIN\r\n", "\tDECLARE @ReturnCols NVARCHAR(max)\r\n", "\t;WITH ColumnToPivot ([data()]) AS ( \r\n", "\t\tSELECT CONVERT(VARCHAR(3),ic.column_id) + N\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027 \r\n", "\t\tFROM sys.dm_db_missing_index_details id \r\n", "\t\tCROSS APPLY sys.dm_db_missing_index_columns(id.index_handle) ic\r\n", "\t\tWHERE id.index_handle = @ix_handle \r\n", "\t\tORDER BY ic.column_id ASC\r\n", "\t\tFOR XML PATH(\u0027\u0027\u0027\u0027\u0027\u0027\u0027\u0027), TYPE \r\n", "\t\t), \r\n", "\t\tXmlRawData (CSVString) AS ( \r\n", "\t\t\tSELECT (SELECT [data()] AS InputData \r\n", "\t\t\tFROM ColumnToPivot AS d FOR XML RAW, TYPE).value(\u0027\u0027\u0027\u0027/row[1]/InputData[1]\u0027\u0027\u0027\u0027, \u0027\u0027\u0027\u0027NVARCHAR(max)\u0027\u0027\u0027\u0027) AS CSVCol \r\n", "\t\t) \r\n", "\tSELECT @ReturnCols = CASE WHEN LEN(CSVString) <= 1 THEN NULL ELSE LEFT(CSVString, LEN(CSVString)-1) END\r\n", "\tFROM XmlRawData\r\n", "\tRETURN (@ReturnCols)\r\n", "END\u0027\u0027)\r\n", "\t\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_keycols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_keycols\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; EXEC(\u0027\u0027\r\n", "CREATE FUNCTION dbo.fn_createindex_keycols (@ix_handle int)\r\n", "RETURNS NVARCHAR(max)\r\n", "AS\r\n", "BEGIN\r\n", "\tDECLARE @ReturnCols NVARCHAR(max)\r\n", "\t;WITH ColumnToPivot ([data()]) AS ( \r\n", "\t\tSELECT CONVERT(VARCHAR(3),ic.column_id) + N\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027 \r\n", "\t\tFROM sys.dm_db_missing_index_details id \r\n", "\t\tCROSS APPLY sys.dm_db_missing_index_columns(id.index_handle) ic\r\n", "\t\tWHERE id.index_handle = @ix_handle\r\n", "\t\tAND (ic.column_usage = \u0027\u0027\u0027\u0027EQUALITY\u0027\u0027\u0027\u0027 OR ic.column_usage = \u0027\u0027\u0027\u0027INEQUALITY\u0027\u0027\u0027\u0027)\r\n", "\t\tORDER BY ic.column_id ASC\r\n", "\t\tFOR XML PATH(\u0027\u0027\u0027\u0027\u0027\u0027\u0027\u0027), TYPE \r\n", "\t\t), \r\n", "\t\tXmlRawData (CSVString) AS ( \r\n", "\t\t\tSELECT (SELECT [data()] AS InputData \r\n", "\t\t\tFROM ColumnToPivot AS d FOR XML RAW, TYPE).value(\u0027\u0027\u0027\u0027/row[1]/InputData[1]\u0027\u0027\u0027\u0027, \u0027\u0027\u0027\u0027NVARCHAR(max)\u0027\u0027\u0027\u0027) AS CSVCol \r\n", "\t\t) \r\n", "\tSELECT @ReturnCols = CASE WHEN LEN(CSVString) <= 1 THEN NULL ELSE LEFT(CSVString, LEN(CSVString)-1) END\r\n", "\tFROM XmlRawData\r\n", "\tRETURN (@ReturnCols)\r\n", "END\u0027\u0027)\r\n", "\t\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_includecols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_includecols\u0027)\r\n", "\t\tEXEC (\u0027USE tempdb; EXEC(\u0027\u0027\r\n", "CREATE FUNCTION dbo.fn_createindex_includecols (@ix_handle int)\r\n", "RETURNS NVARCHAR(max)\r\n", "AS\r\n", "BEGIN\r\n", "\tDECLARE @ReturnCols NVARCHAR(max)\r\n", "\t;WITH ColumnToPivot ([data()]) AS ( \r\n", "\t\tSELECT CONVERT(VARCHAR(3),ic.column_id) + N\u0027\u0027\u0027\u0027,\u0027\u0027\u0027\u0027 \r\n", "\t\tFROM sys.dm_db_missing_index_details id \r\n", "\t\tCROSS APPLY sys.dm_db_missing_index_columns(id.index_handle) ic\r\n", "\t\tWHERE id.index_handle = @ix_handle\r\n", "\t\tAND ic.column_usage = \u0027\u0027\u0027\u0027INCLUDE\u0027\u0027\u0027\u0027\r\n", "\t\tORDER BY ic.column_id ASC\r\n", "\t\tFOR XML PATH(\u0027\u0027\u0027\u0027\u0027\u0027\u0027\u0027), TYPE \r\n", "\t\t), \r\n", "\t\tXmlRawData (CSVString) AS ( \r\n", "\t\t\tSELECT (SELECT [data()] AS InputData \r\n", "\t\t\tFROM ColumnToPivot AS d FOR XML RAW, TYPE).value(\u0027\u0027\u0027\u0027/row[1]/InputData[1]\u0027\u0027\u0027\u0027, \u0027\u0027\u0027\u0027NVARCHAR(max)\u0027\u0027\u0027\u0027) AS CSVCol \r\n", "\t\t) \r\n", "\tSELECT @ReturnCols = CASE WHEN LEN(CSVString) <= 1 THEN NULL ELSE LEFT(CSVString, LEN(CSVString)-1) END\r\n", "\tFROM XmlRawData\r\n", "\tRETURN (@ReturnCols)\r\n", "END\u0027\u0027)\r\n", "\t\u0027)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexCreation\u0027))\r\n", "\tDROP TABLE #IndexCreation;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexCreation\u0027))\r\n", "\tCREATE TABLE #IndexCreation\r\n", "\t\t(\r\n", "\t\t\t[database_id] int,\r\n", "\t\t\tDBName NVARCHAR(1000),\r\n", "\t\t\t[Table] NVARCHAR(255),\r\n", "\t\t\t[ix_handle] int,\r\n", "\t\t\t[User_Hits_on_Missing_Index] bigint,\r\n", "\t\t\t[Estimated_Improvement_Percent] DECIMAL(5,2),\r\n", "\t\t\t[Avg_Total_User_Cost] float,\r\n", "\t\t\t[Unique_Compiles] bigint,\r\n", "\t\t\t[Score] NUMERIC(19,3),\r\n", "\t\t\t[KeyCols] NVARCHAR(1000),\r\n", "\t\t\t[IncludedCols] NVARCHAR(4000),\r\n", "\t\t\t[Ix_Name] NVARCHAR(255),\r\n", "\t\t\t[AllCols] NVARCHAR(max),\r\n", "\t\t\t[KeyColsOrdered] NVARCHAR(max),\r\n", "\t\t\t[IncludedColsOrdered] NVARCHAR(max)\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexRedundant\u0027))\r\n", "\tDROP TABLE #IndexRedundant;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexRedundant\u0027))\r\n", "\tCREATE TABLE #IndexRedundant\r\n", "\t\t(\r\n", "\t\t\tDBName NVARCHAR(1000),\r\n", "\t\t\t[Table] NVARCHAR(255),\r\n", "\t\t\t[Ix_Name] NVARCHAR(255),\r\n", "\t\t\t[ix_handle] int,\r\n", "\t\t\t[KeyCols] NVARCHAR(1000),\r\n", "\t\t\t[IncludedCols] NVARCHAR(4000),\r\n", "\t\t\t[Redundant_With] NVARCHAR(255)\r\n", "\t\t)\r\n", "\t\tINSERT INTO #IndexCreation\r\n", "\t\tSELECT i.database_id,\r\n", "\t\t\tm.[name],\r\n", "\t\t\tRIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3)) AS [Table],\r\n", "\t\t\ti.index_handle AS [ix_handle],\r\n", "\t\t\t[User_Hits_on_Missing_Index] = (s.user_seeks + s.user_scans),\r\n", "\t\t\ts.avg_user_impact, -- Query cost would reduce by this amount in percentage, on average.\r\n", "\t\t\ts.avg_total_user_cost, -- Average cost of the user queries that could be reduced by the index in the group.\r\n", "\t\t\ts.unique_compiles, -- Number of compilations and recompilations that would benefit from this missing index group.\r\n", "\t\t\t(CONVERT(NUMERIC(19,3), s.user_seeks) + CONVERT(NUMERIC(19,3), s.user_scans)) \r\n", "\t\t\t* CONVERT(NUMERIC(19,3), s.avg_total_user_cost) \r\n", "\t\t\t* CONVERT(NUMERIC(19,3), s.avg_user_impact) AS Score, -- The higher the score, higher is the anticipated improvement for user queries.\r\n", "\t\t\tCASE WHEN (i.equality_columns IS NOT NULL AND i.inequality_columns IS NULL) THEN i.equality_columns\r\n", "\t\t\t\tWHEN (i.equality_columns IS NULL AND i.inequality_columns IS NOT NULL) THEN i.inequality_columns\r\n", "\t\t\t\tELSE i.equality_columns + \u0027,\u0027 + i.inequality_columns END AS [KeyCols],\r\n", "\t\t\ti.included_columns AS [IncludedCols],\r\n", "\t\t\t\u0027IX_\u0027 + LEFT(RIGHT(RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3)), LEN(RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3))) - (CHARINDEX(\u0027.\u0027, RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3)), 1)) - 1),\r\n", "\t\t\tLEN(RIGHT(RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3)), LEN(RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3))) - (CHARINDEX(\u0027.\u0027, RIGHT(i.[statement], LEN(i.[statement]) - (LEN(m.[name]) + 3)), 1)) - 1)) - 1) + \u0027_\u0027 + CAST(i.index_handle AS NVARCHAR) AS [Ix_Name],\r\n", "\t\t\ttempdb.dbo.fn_createindex_allcols(i.index_handle),\r\n", "\t\t\ttempdb.dbo.fn_createindex_keycols(i.index_handle),\r\n", "\t\t\ttempdb.dbo.fn_createindex_includecols(i.index_handle)\r\n", "\t\tFROM sys.dm_db_missing_index_details i\r\n", "\t\t\tINNER JOIN master.sys.databases m ON i.database_id = m.database_id\r\n", "\t\t\tINNER JOIN sys.dm_db_missing_index_groups g ON i.index_handle = g.index_handle\r\n", "\t\t\tINNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle\r\n", "\t\tWHERE i.database_id > 4\r\n", "\t\tINSERT INTO #IndexRedundant\r\n", "\t\tSELECT I.DBName, I.[Table], I.[Ix_Name], I.[ix_handle], I.[KeyCols], I.[IncludedCols], I2.[Ix_Name]\r\n", "\t\tFROM #IndexCreation I\r\n", "\t\t\tINNER JOIN #IndexCreation I2 ON I.[database_id] = I2.[database_id] AND I.[Table] = I2.[Table] AND I.[Ix_Name] <> I2.[Ix_Name]\r\n", "\t\t\t\tAND (((I.KeyColsOrdered <> I2.KeyColsOrdered OR I.[IncludedColsOrdered] <> I2.[IncludedColsOrdered])\r\n", "\t\t\t\tAND ((CASE WHEN I.[IncludedColsOrdered] IS NULL THEN I.KeyColsOrdered ELSE I.KeyColsOrdered + \u0027,\u0027 + I.[IncludedColsOrdered] END) = (CASE WHEN I2.[IncludedColsOrdered] IS NULL THEN I2.KeyColsOrdered ELSE I2.KeyColsOrdered + \u0027,\u0027 + I2.[IncludedColsOrdered] END)\r\n", "\t\t\t\tOR I.[AllCols] = I2.[AllCols]))\r\n", "\t\t\t\tOR (I.KeyColsOrdered <> I2.KeyColsOrdered AND I.[IncludedColsOrdered] = I2.[IncludedColsOrdered])\r\n", "\t\t\t\tOR (I.KeyColsOrdered = I2.KeyColsOrdered AND I.[IncludedColsOrdered] <> I2.[IncludedColsOrdered]))\r\n", "\t\tWHERE I.[Score] >= 100000\r\n", "\t\t\tAND I2.[Score] >= 100000\r\n", "\t\tGROUP BY I.DBName, I.[Table], I.[Ix_Name], I.[ix_handle], I.[KeyCols], I.[IncludedCols], I2.[Ix_Name]\r\n", "\t\tORDER BY I.DBName, I.[Table], I.[Ix_Name]\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #IndexCreation\r\n", "\t\tWHERE [Score] >= 100000) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Check], \u0027[INFORMATION: Potentially missing indexes were found. It may be important to revise these]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Information], IC.DBName AS [Database_Name], IC.[Table] AS [Table_Name], CONVERT(bigint,[Score]) AS [Score], [User_Hits_on_Missing_Index],\r\n", "\t\t\t\t[Estimated_Improvement_Percent], [Avg_Total_User_Cost], [Unique_Compiles], IC.[KeyCols], IC.[IncludedCols], IC.[Ix_Name] AS [Index_Name],\r\n", "\t\t\t\tSUBSTRING((SELECT \u0027,\u0027 + IR.[Redundant_With]\r\n", "\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]\r\n", "\t\t\t\tORDER BY IR.[Redundant_With]\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027)), 2, 8000) AS [Possibly_Redundant_With],\r\n", "\t\t\t\tCASE WHEN IC.[Score] >= 100000 THEN \u0027Y\u0027 ELSE \u0027N\u0027 END AS [Generate_Script]\r\n", "\t\t\tFROM #IndexCreation IC\r\n", "\t\t--WHERE [Score] >= 100000\r\n", "\t\t--ORDER BY IC.DBName, IC.[Score] DESC, IC.[User_Hits_on_Missing_Index], IC.[Estimated_Improvement_Percent];\r\n", "\t\t\tORDER BY IC.[Score] DESC;\r\n", "\t\t\tSELECT DISTINCT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Check], \u0027Possibly_redundant_IXs_in_list\u0027 AS Comments, I.DBName AS [Database_Name], I.[Table] AS [Table_Name],\r\n", "\t\t\t\tI.[Ix_Name] AS [Index_Name], I.[KeyCols], I.[IncludedCols]\r\n", "\t\t\tFROM #IndexRedundant I\r\n", "\t\t\tORDER BY I.DBName, I.[Table], I.[Ix_Name]\r\n", "\t\t\tIF @gen_scripts = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tPRINT CHAR(10) + \u0027/* Generated on \u0027 + CONVERT (VARCHAR, GETDATE()) + \u0027 in \u0027 + @@SERVERNAME + \u0027 */\u0027 + CHAR(10)\r\n", "\t\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #IndexCreation IC\r\n", "\t\t\t\tWHERE IC.[IncludedCols] IS NULL AND IC.[Score] >= 100000\r\n", "\t\t\t\t) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT \u0027--############# Indexes creation statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\t\tDECLARE cIC CURSOR FAST_FORWARD FOR\r\n", "\t\t\t\tSELECT \u0027-- User Hits on Missing Index \u0027 + IC.[Ix_Name] + \u0027: \u0027 + CONVERT(VARCHAR(20),IC.[User_Hits_on_Missing_Index]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Estimated Improvement Percent: \u0027 + CONVERT(VARCHAR(6),IC.[Estimated_Improvement_Percent]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Average Total User Cost: \u0027 + CONVERT(VARCHAR(50),IC.[Avg_Total_User_Cost]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Unique Compiles: \u0027 + CONVERT(VARCHAR(50),IC.[Unique_Compiles]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Score: \u0027 + CONVERT(VARCHAR(20),CONVERT(bigint,IC.[Score])) + \r\n", "\t\t\t\t\tCASE WHEN (SELECT COUNT(IR.[Redundant_With])\r\n", "\t\t\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]) > 0 \r\n", "\t\t\t\t\tTHEN CHAR(10) + \u0027-- Possibly Redundant with Missing Index(es): \u0027 + SUBSTRING((SELECT \u0027,\u0027 + IR.[Redundant_With]\r\n", "\t\t\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]\r\n", "\t\t\t\t\t\tFOR XML PATH(\u0027\u0027)), 2, 8000) \r\n", "\t\t\t\t\tELSE \u0027\u0027 END +\r\n", "\t\t\t\t\tCHAR(10) + \u0027USE \u0027 + QUOTENAME(IC.DBName) + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sysindexes WHERE name = N\u0027\u0027\u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027\u0027\u0027) DROP INDEX \u0027 + IC.[Table] + \u0027.\u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027CREATE INDEX \u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027 ON \u0027 + IC.[Table] + \u0027 (\u0027 + IC.[KeyCols] + CASE WHEN @editionCheck = 1 THEN \u0027) WITH (ONLINE = ON);\u0027 ELSE \u0027);\u0027 END + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\t\tFROM #IndexCreation IC\r\n", "\t\t\t\t\tWHERE IC.[IncludedCols] IS NULL AND IC.[Score] >= 100000\r\n", "\t\t\t\t\tORDER BY IC.DBName, IC.[Table], IC.[Ix_Name]\r\n", "\t\t\t\t\tOPEN cIC\r\n", "\t\t\t\t\tFETCH NEXT FROM cIC INTO @IC\r\n", "\t\t\t\t\tWHILE @@FETCH_STATUS = 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tPRINT @IC\r\n", "\t\t\t\t\t\tFETCH NEXT FROM cIC INTO @IC\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tCLOSE cIC\r\n", "\t\t\t\t\tDEALLOCATE cIC\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tIF (SELECT COUNT(*)\r\n", "\t\t\t\tFROM #IndexCreation IC\r\n", "\t\t\t\tWHERE IC.[IncludedCols] IS NOT NULL AND IC.[Score] >= 100000\r\n", "\t\t\t\t) > 0\r\n", "\t\t\tBEGIN\r\n", "\t\t\t\t\tPRINT \u0027--############# Covering indexes creation statements #############\u0027 + CHAR(10)\r\n", "\t\t\t\t\tDECLARE cICWI CURSOR FAST_FORWARD FOR\r\n", "\t\t\t\tSELECT \u0027-- User Hits on Missing Index \u0027 + IC.[Ix_Name] + \u0027: \u0027 + CONVERT(VARCHAR(20),IC.[User_Hits_on_Missing_Index]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Estimated Improvement Percent: \u0027 + CONVERT(VARCHAR(6),IC.[Estimated_Improvement_Percent]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Average Total User Cost: \u0027 + CONVERT(VARCHAR(50),IC.[Avg_Total_User_Cost]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Unique Compiles: \u0027 + CONVERT(VARCHAR(50),IC.[Unique_Compiles]) + CHAR(10) +\r\n", "\t\t\t\t\t\u0027-- Score: \u0027 + CONVERT(VARCHAR(20),CONVERT(bigint,IC.[Score])) + \r\n", "\t\t\t\t\tCASE WHEN (SELECT COUNT(IR.[Redundant_With])\r\n", "\t\t\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]) > 0 \r\n", "\t\t\t\t\tTHEN CHAR(10) + \u0027-- Possibly Redundant with Missing Index(es): \u0027 + SUBSTRING((SELECT \u0027,\u0027 + IR.[Redundant_With]\r\n", "\t\t\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]\r\n", "\t\t\t\t\t\tFOR XML PATH(\u0027\u0027)), 2, 8000) \r\n", "\t\t\t\t\tELSE \u0027\u0027 END + \r\n", "\t\t\t\t\tCHAR(10) + \u0027USE \u0027 + QUOTENAME(IC.DBName) + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027IF EXISTS (SELECT name FROM sysindexes WHERE name = N\u0027\u0027\u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027\u0027\u0027) DROP INDEX \u0027 + IC.[Table] + \u0027.\u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027;\u0027 + CHAR(10) + \u0027GO\u0027 + CHAR(10) + \u0027CREATE INDEX \u0027 +\r\n", "\t\t\t\t\tIC.[Ix_Name] + \u0027 ON \u0027 + IC.[Table] + \u0027 (\u0027 + IC.[KeyCols] + \u0027)\u0027 + CHAR(10) + \u0027INCLUDE(\u0027 + IC.[IncludedCols] + CASE WHEN @editionCheck = 1 THEN \u0027) WITH (ONLINE = ON);\u0027 ELSE \u0027);\u0027 END + CHAR(10) + \u0027GO\u0027 + CHAR(10)\r\n", "\t\t\t\t\tFROM #IndexCreation IC\r\n", "\t\t\t\t\tWHERE IC.[IncludedCols] IS NOT NULL AND IC.[Score] >= 100000\r\n", "\t\t\t\t\tORDER BY IC.DBName, IC.[Table], IC.[Ix_Name]\r\n", "\t\t\t\t\tOPEN cICWI\r\n", "\t\t\t\t\tFETCH NEXT FROM cICWI INTO @ICWI\r\n", "\t\t\t\t\tWHILE @@FETCH_STATUS = 0\r\n", "\t\t\t\t\tBEGIN\r\n", "\t\t\t\t\t\tPRINT @ICWI\r\n", "\t\t\t\t\t\tFETCH NEXT FROM cICWI INTO @ICWI\r\n", "\t\t\t\t\tEND\r\n", "\t\t\t\t\tCLOSE cICWI\r\n", "\t\t\t\t\tDEALLOCATE cICWI\r\n", "\t\t\t\tEND;\r\n", "\t\t\t\tPRINT \u0027--############# Ended missing indexes creation statements #############\u0027 + CHAR(10)\r\n", "\t\t\tEND;\r\n", "\t\tEND\r\n", "\tELSE IF (SELECT COUNT(*)\r\n", "\t\tFROM #IndexCreation\r\n", "\t\tWHERE [Score] < 100000) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Check], \u0027[INFORMATION: no relevant missing indexes were found, although missing indexes were identified by SQL Server]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Information], IC.DBName AS [Database_Name], IC.[Table] AS [Table_Name], CONVERT(bigint,[Score]) AS [Score], [User_Hits_on_Missing_Index],\r\n", "\t\t\t\t[Estimated_Improvement_Percent], [Avg_Total_User_Cost], [Unique_Compiles], IC.[KeyCols], IC.[IncludedCols], IC.[Ix_Name] AS [Index_Name],\r\n", "\t\t\t\tSUBSTRING((SELECT \u0027,\u0027 + IR.[Redundant_With]\r\n", "\t\t\t\tFROM #IndexRedundant IR\r\n", "\t\t\t\tWHERE IC.DBName = IR.DBName AND IC.[Table] = IR.[Table] AND IC.[ix_handle] = IR.[ix_handle]\r\n", "\t\t\t\tORDER BY IR.[Redundant_With]\r\n", "\t\t\t\tFOR XML PATH(\u0027\u0027)), 2, 8000) AS [Possibly_Redundant_With],\r\n", "\t\t\t\tCASE WHEN IC.[Score] >= 100000 THEN \u0027Y\u0027 ELSE \u0027N\u0027 END AS [Generate_Script]\r\n", "\t\t\tFROM #IndexCreation IC\r\n", "\t\t--WHERE [Score] < 100000\r\n", "\t\t\tORDER BY IC.DBName, IC.[Score] DESC, IC.[User_Hits_on_Missing_Index], IC.[Estimated_Improvement_Percent];\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Index_and_Stats_checks\u0027 AS [Category], \u0027Missing_Indexes\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "f92ee6a7-759b-4903-ae65-dbadedbbd814", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Objects naming conventions subsection\r\n", "Refer to BOL for more information \r\n", "https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172115(v=vs.100) \r\n", "https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172134(v=vs.100) \r\n", "https://docs.microsoft.com/sql/t-sql/language-elements/reserved-keywords-transact-sql\r\n" ], "metadata": { "azdata_cell_guid": "0a75936a-c617-448c-97e3-5b4511079e44" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027|-Starting Objects naming conventions Checks\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpobjectnames\u0027))\r\n", "DROP TABLE #tmpobjectnames;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpobjectnames\u0027))\r\n", "CREATE TABLE #tmpobjectnames\r\n", "\t(\r\n", "\t\t[DBName] sysname,\r\n", "\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t[Object] NVARCHAR(255),\r\n", "\t\t[Col] NVARCHAR(255),\r\n", "\t\t[type] CHAR(2),\r\n", "\t\ttype_desc NVARCHAR(60)\r\n", "\t);\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpfinalobjectnames\u0027))\r\n", "DROP TABLE #tmpfinalobjectnames;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpfinalobjectnames\u0027))\r\n", "CREATE TABLE #tmpfinalobjectnames\r\n", "\t(\r\n", "\t\t[Deviation] tinyint,\r\n", "\t\t[DBName] sysname,\r\n", "\t\t[schemaName] NVARCHAR(100),\r\n", "\t\t[Object] NVARCHAR(255),\r\n", "\t\t[Col] NVARCHAR(255),\r\n", "\t\ttype_desc NVARCHAR(60),\r\n", "\t\t[Comment] NVARCHAR(500) NULL\r\n", "\t);\r\n", "\tUPDATE tempdb.dbo.tmpdbs1\r\n", "SET isdone = 0\r\n", "\tWHILE (SELECT COUNT(id)\r\n", "\tFROM tempdb.dbo.tmpdbs1\r\n", "\tWHERE isdone = 0) > 0\r\n", "BEGIN\r\n", "\t\tSELECT TOP 1\r\n", "\t\t\t@dbname = [dbname], @dbid = [dbid]\r\n", "\t\tFROM tempdb.dbo.tmpdbs1\r\n", "\t\tWHERE isdone = 0\r\n", "\t\tSET @sqlcmd = \u0027USE \u0027 + QUOTENAME(@dbname) + \u0027;\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], s.name, so.name, NULL, type, type_desc\r\n", "FROM sys.objects so \r\n", "INNER JOIN sys.schemas s ON so.schema_id = s.schema_id\r\n", "WHERE so.is_ms_shipped = 0\r\n", "UNION ALL\r\n", "SELECT \u0027\u0027\u0027 + REPLACE(@dbname, CHAR(39), CHAR(95)) + \u0027\u0027\u0027 AS [DBName], s.name, so.name, sc.name, \u0027\u0027TC\u0027\u0027 AS [type], \u0027\u0027TABLE_COLUMN\u0027\u0027 AS [type_desc]\r\n", "FROM sys.columns sc \r\n", "INNER JOIN sys.objects so ON sc.object_id = so.object_id\r\n", "INNER JOIN sys.schemas s ON so.schema_id = s.schema_id\r\n", "WHERE so.is_ms_shipped = 0\u0027\r\n", "\t\tBEGIN TRY\r\n", "\t\tINSERT INTO #tmpobjectnames\r\n", "\t\tEXECUTE sp_executesql @sqlcmd\r\n", "\tEND TRY\r\n", "\tBEGIN CATCH\r\n", "\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\tSELECT @ErrorMessage = \u0027Object naming conventions subsection - Error raised in TRY block in database \u0027 + @dbname +\u0027. \u0027 + ERROR_MESSAGE()\r\n", "\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\tEND CATCH\r\n", "\t\tUPDATE tempdb.dbo.tmpdbs1\r\n", "\tSET isdone = 1\r\n", "\tWHERE [dbid] = @dbid\r\n", "\tEND;\r\n", "\tUPDATE tempdb.dbo.tmpdbs1\r\n", "SET isdone = 0\r\n", "\tCREATE INDEX IX1 ON #tmpobjectnames([type],[Object]);\r\n", "\t/* https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172115(v=vs.100) */\r\n", "\tINSERT INTO #tmpfinalobjectnames\r\n", "\tSELECT 1, [DBName], [schemaName], [Object], [Col], type_desc, NULL\r\n", "\tFROM #tmpobjectnames\r\n", "\tWHERE [type] = \u0027P\u0027 AND [Object] LIKE \u0027sp[_]%\u0027\r\n", "\t\tAND [Object] NOT IN (\u0027sp_alterdiagram\u0027,\u0027sp_creatediagram\u0027,\u0027sp_dropdiagram\u0027,\u0027sp_helpdiagramdefinition\u0027,\u0027sp_helpdiagrams\u0027,\u0027sp_renamediagram\u0027,\u0027sp_upgraddiagrams\u0027);\r\n", "\t/* https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2010/dd172134(v=vs.100) */\r\n", "\tINSERT INTO #tmpfinalobjectnames\r\n", "\tSELECT 2, [DBName], [schemaName], [Object], [Col], type_desc, CASE WHEN [Object] LIKE \u0027% %\u0027 THEN \u0027Space - \u0027 + QUOTENAME([Object]) ELSE NULL END COLLATE database_default AS [Comment]\r\n", "\tFROM #tmpobjectnames\r\n", "\tWHERE [type] <> \u0027S\u0027 AND [type] <> \u0027TC\u0027\r\n", "\t\tAND ([Object] LIKE \u0027% %\u0027 --space\r\n", "\t\tOR [Object] LIKE \u0027%[[]%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%]%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%-%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%.%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%,%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%;%\u0027\r\n", "\t\tOR [Object] LIKE \u0027%\u0027 + CHAR(34) + \u0027%\u0027 --double quote\r\n", "\t\tOR [Object] LIKE \u0027%\u0027 + CHAR(39) + \u0027%\u0027);\r\n", "--single quote\r\n", "\tINSERT INTO #tmpfinalobjectnames\r\n", "\tSELECT 3, [DBName], [schemaName], [Object], [Col], type_desc, CASE WHEN [Col] LIKE \u0027% %\u0027 THEN \u0027Space - \u0027 + QUOTENAME([Col]) ELSE NULL END COLLATE database_default AS [Comment]\r\n", "\tFROM #tmpobjectnames\r\n", "\tWHERE [type] = \u0027TC\u0027\r\n", "\t\tAND ([Col] LIKE \u0027% %\u0027 --space\r\n", "\t\tOR [Col] LIKE \u0027%[[]%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%]%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%-%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%.%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%,%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%;%\u0027\r\n", "\t\tOR [Col] LIKE \u0027%\u0027 + CHAR(34) + \u0027%\u0027 --double quote\r\n", "\t\tOR [Col] LIKE \u0027%\u0027 + CHAR(39) + \u0027%\u0027);\r\n", "--single quote\r\n", "\t/* https://docs.microsoft.com/sql/t-sql/language-elements/reserved-keywords-transact-sql */\r\n", "\tINSERT INTO #tmpfinalobjectnames\r\n", "\tSELECT 4, [DBName], [schemaName], [Object], [Col], type_desc, NULL\r\n", "\tFROM #tmpobjectnames\r\n", "\tWHERE [type] <> \u0027S\u0027\r\n", "\t\tAND ([Object] LIKE \u0027% ABSOLUTE %\u0027 OR [Object] LIKE \u0027% ABSOLUTE\u0027 OR [Object] = \u0027ABSOLUTE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ACTION %\u0027 OR [Object] LIKE \u0027% ACTION\u0027 OR [Object] = \u0027ACTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ADA %\u0027 OR [Object] LIKE \u0027% ADA\u0027 OR [Object] = \u0027ADA\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ADD %\u0027 OR [Object] LIKE \u0027% ADD\u0027 OR [Object] = \u0027ADD\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ADMIN %\u0027 OR [Object] LIKE \u0027% ADMIN\u0027 OR [Object] = \u0027ADMIN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AFTER %\u0027 OR [Object] LIKE \u0027% AFTER\u0027 OR [Object] = \u0027AFTER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AGGREGATE %\u0027 OR [Object] LIKE \u0027% AGGREGATE\u0027 OR [Object] = \u0027AGGREGATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ALIAS %\u0027 OR [Object] LIKE \u0027% ALIAS\u0027 OR [Object] = \u0027ALIAS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ALL %\u0027 OR [Object] LIKE \u0027% ALL\u0027 OR [Object] = \u0027ALL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ALLOCATE %\u0027 OR [Object] LIKE \u0027% ALLOCATE\u0027 OR [Object] = \u0027ALLOCATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ALTER %\u0027 OR [Object] LIKE \u0027% ALTER\u0027 OR [Object] = \u0027ALTER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AND %\u0027 OR [Object] LIKE \u0027% AND\u0027 OR [Object] = \u0027AND\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ANY %\u0027 OR [Object] LIKE \u0027% ANY\u0027 OR [Object] = \u0027ANY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ARE %\u0027 OR [Object] LIKE \u0027% ARE\u0027 OR [Object] = \u0027ARE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ARRAY %\u0027 OR [Object] LIKE \u0027% ARRAY\u0027 OR [Object] = \u0027ARRAY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AS %\u0027 OR [Object] LIKE \u0027% AS\u0027 OR [Object] = \u0027AS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ASC %\u0027 OR [Object] LIKE \u0027% ASC\u0027 OR [Object] = \u0027ASC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ASSERTION %\u0027 OR [Object] LIKE \u0027% ASSERTION\u0027 OR [Object] = \u0027ASSERTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AT %\u0027 OR [Object] LIKE \u0027% AT\u0027 OR [Object] = \u0027AT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AUTHORIZATION %\u0027 OR [Object] LIKE \u0027% AUTHORIZATION\u0027 OR [Object] = \u0027AUTHORIZATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% AVG %\u0027 OR [Object] LIKE \u0027% AVG\u0027 OR [Object] = \u0027AVG\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BACKUP %\u0027 OR [Object] LIKE \u0027% BACKUP\u0027 OR [Object] = \u0027BACKUP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BEFORE %\u0027 OR [Object] LIKE \u0027% BEFORE\u0027 OR [Object] = \u0027BEFORE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BEGIN %\u0027 OR [Object] LIKE \u0027% BEGIN\u0027 OR [Object] = \u0027BEGIN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BETWEEN %\u0027 OR [Object] LIKE \u0027% BETWEEN\u0027 OR [Object] = \u0027BETWEEN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BINARY %\u0027 OR [Object] LIKE \u0027% BINARY\u0027 OR [Object] = \u0027BINARY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BIT %\u0027 OR [Object] LIKE \u0027% BIT\u0027 OR [Object] = \u0027BIT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BIT_LENGTH %\u0027 OR [Object] LIKE \u0027% BIT_LENGTH\u0027 OR [Object] = \u0027BIT_LENGTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BLOB %\u0027 OR [Object] LIKE \u0027% BLOB\u0027 OR [Object] = \u0027BLOB\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BOOLEAN %\u0027 OR [Object] LIKE \u0027% BOOLEAN\u0027 OR [Object] = \u0027BOOLEAN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BOTH %\u0027 OR [Object] LIKE \u0027% BOTH\u0027 OR [Object] = \u0027BOTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BREADTH %\u0027 OR [Object] LIKE \u0027% BREADTH\u0027 OR [Object] = \u0027BREADTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BREAK %\u0027 OR [Object] LIKE \u0027% BREAK\u0027 OR [Object] = \u0027BREAK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BROWSE %\u0027 OR [Object] LIKE \u0027% BROWSE\u0027 OR [Object] = \u0027BROWSE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BULK %\u0027 OR [Object] LIKE \u0027% BULK\u0027 OR [Object] = \u0027BULK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% BY %\u0027 OR [Object] LIKE \u0027% BY\u0027 OR [Object] = \u0027BY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CALL %\u0027 OR [Object] LIKE \u0027% CALL\u0027 OR [Object] = \u0027CALL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CASCADE %\u0027 OR [Object] LIKE \u0027% CASCADE\u0027 OR [Object] = \u0027CASCADE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CASCADED %\u0027 OR [Object] LIKE \u0027% CASCADED\u0027 OR [Object] = \u0027CASCADED\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CASE %\u0027 OR [Object] LIKE \u0027% CASE\u0027 OR [Object] = \u0027CASE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CAST %\u0027 OR [Object] LIKE \u0027% CAST\u0027 OR [Object] = \u0027CAST\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CATALOG %\u0027 OR [Object] LIKE \u0027% CATALOG\u0027 OR [Object] = \u0027CATALOG\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHAR %\u0027 OR [Object] LIKE \u0027% CHAR\u0027 OR [Object] = \u0027CHAR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHAR_LENGTH %\u0027 OR [Object] LIKE \u0027% CHAR_LENGTH\u0027 OR [Object] = \u0027CHAR_LENGTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHARACTER %\u0027 OR [Object] LIKE \u0027% CHARACTER\u0027 OR [Object] = \u0027CHARACTER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHARACTER_LENGTH %\u0027 OR [Object] LIKE \u0027% CHARACTER_LENGTH\u0027 OR [Object] = \u0027CHARACTER_LENGTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHECK %\u0027 OR [Object] LIKE \u0027% CHECK\u0027 OR [Object] = \u0027CHECK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CHECKPOINT %\u0027 OR [Object] LIKE \u0027% CHECKPOINT\u0027 OR [Object] = \u0027CHECKPOINT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CLASS %\u0027 OR [Object] LIKE \u0027% CLASS\u0027 OR [Object] = \u0027CLASS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CLOB %\u0027 OR [Object] LIKE \u0027% CLOB\u0027 OR [Object] = \u0027CLOB\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CLOSE %\u0027 OR [Object] LIKE \u0027% CLOSE\u0027 OR [Object] = \u0027CLOSE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CLUSTERED %\u0027 OR [Object] LIKE \u0027% CLUSTERED\u0027 OR [Object] = \u0027CLUSTERED\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COALESCE %\u0027 OR [Object] LIKE \u0027% COALESCE\u0027 OR [Object] = \u0027COALESCE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COLLATE %\u0027 OR [Object] LIKE \u0027% COLLATE\u0027 OR [Object] = \u0027COLLATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COLLATION %\u0027 OR [Object] LIKE \u0027% COLLATION\u0027 OR [Object] = \u0027COLLATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COLUMN %\u0027 OR [Object] LIKE \u0027% COLUMN\u0027 OR [Object] = \u0027COLUMN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COMMIT %\u0027 OR [Object] LIKE \u0027% COMMIT\u0027 OR [Object] = \u0027COMMIT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COMPLETION %\u0027 OR [Object] LIKE \u0027% COMPLETION\u0027 OR [Object] = \u0027COMPLETION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COMPUTE %\u0027 OR [Object] LIKE \u0027% COMPUTE\u0027 OR [Object] = \u0027COMPUTE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONNECT %\u0027 OR [Object] LIKE \u0027% CONNECT\u0027 OR [Object] = \u0027CONNECT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONNECTION %\u0027 OR [Object] LIKE \u0027% CONNECTION\u0027 OR [Object] = \u0027CONNECTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONSTRAINT %\u0027 OR [Object] LIKE \u0027% CONSTRAINT\u0027 OR [Object] = \u0027CONSTRAINT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONSTRAINTS %\u0027 OR [Object] LIKE \u0027% CONSTRAINTS\u0027 OR [Object] = \u0027CONSTRAINTS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONSTRUCTOR %\u0027 OR [Object] LIKE \u0027% CONSTRUCTOR\u0027 OR [Object] = \u0027CONSTRUCTOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONTAINS %\u0027 OR [Object] LIKE \u0027% CONTAINS\u0027 OR [Object] = \u0027CONTAINS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONTAINSTABLE %\u0027 OR [Object] LIKE \u0027% CONTAINSTABLE\u0027 OR [Object] = \u0027CONTAINSTABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONTINUE %\u0027 OR [Object] LIKE \u0027% CONTINUE\u0027 OR [Object] = \u0027CONTINUE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CONVERT %\u0027 OR [Object] LIKE \u0027% CONVERT\u0027 OR [Object] = \u0027CONVERT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CORRESPONDING %\u0027 OR [Object] LIKE \u0027% CORRESPONDING\u0027 OR [Object] = \u0027CORRESPONDING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% COUNT %\u0027 OR [Object] LIKE \u0027% COUNT\u0027 OR [Object] = \u0027COUNT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CREATE %\u0027 OR [Object] LIKE \u0027% CREATE\u0027 OR [Object] = \u0027CREATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CROSS %\u0027 OR [Object] LIKE \u0027% CROSS\u0027 OR [Object] = \u0027CROSS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CUBE %\u0027 OR [Object] LIKE \u0027% CUBE\u0027 OR [Object] = \u0027CUBE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT %\u0027 OR [Object] LIKE \u0027% CURRENT\u0027 OR [Object] = \u0027CURRENT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_DATE %\u0027 OR [Object] LIKE \u0027% CURRENT_DATE\u0027 OR [Object] = \u0027CURRENT_DATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_PATH %\u0027 OR [Object] LIKE \u0027% CURRENT_PATH\u0027 OR [Object] = \u0027CURRENT_PATH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_ROLE %\u0027 OR [Object] LIKE \u0027% CURRENT_ROLE\u0027 OR [Object] = \u0027CURRENT_ROLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_TIME %\u0027 OR [Object] LIKE \u0027% CURRENT_TIME\u0027 OR [Object] = \u0027CURRENT_TIME\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_TIMESTAMP %\u0027 OR [Object] LIKE \u0027% CURRENT_TIMESTAMP\u0027 OR [Object] = \u0027CURRENT_TIMESTAMP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURRENT_USER %\u0027 OR [Object] LIKE \u0027% CURRENT_USER\u0027 OR [Object] = \u0027CURRENT_USER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CURSOR %\u0027 OR [Object] LIKE \u0027% CURSOR\u0027 OR [Object] = \u0027CURSOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% CYCLE %\u0027 OR [Object] LIKE \u0027% CYCLE\u0027 OR [Object] = \u0027CYCLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DATA %\u0027 OR [Object] LIKE \u0027% DATA\u0027 OR [Object] = \u0027DATA\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DATABASE %\u0027 OR [Object] LIKE \u0027% DATABASE\u0027 OR [Object] = \u0027DATABASE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DATE %\u0027 OR [Object] LIKE \u0027% DATE\u0027 OR [Object] = \u0027DATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DAY %\u0027 OR [Object] LIKE \u0027% DAY\u0027 OR [Object] = \u0027DAY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DBCC %\u0027 OR [Object] LIKE \u0027% DBCC\u0027 OR [Object] = \u0027DBCC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEALLOCATE %\u0027 OR [Object] LIKE \u0027% DEALLOCATE\u0027 OR [Object] = \u0027DEALLOCATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEC %\u0027 OR [Object] LIKE \u0027% DEC\u0027 OR [Object] = \u0027DEC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DECIMAL %\u0027 OR [Object] LIKE \u0027% DECIMAL\u0027 OR [Object] = \u0027DECIMAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DECLARE %\u0027 OR [Object] LIKE \u0027% DECLARE\u0027 OR [Object] = \u0027DECLARE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEFAULT %\u0027 OR [Object] LIKE \u0027% DEFAULT\u0027 OR [Object] = \u0027DEFAULT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEFERRABLE %\u0027 OR [Object] LIKE \u0027% DEFERRABLE\u0027 OR [Object] = \u0027DEFERRABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEFERRED %\u0027 OR [Object] LIKE \u0027% DEFERRED\u0027 OR [Object] = \u0027DEFERRED\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DELETE %\u0027 OR [Object] LIKE \u0027% DELETE\u0027 OR [Object] = \u0027DELETE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DENY %\u0027 OR [Object] LIKE \u0027% DENY\u0027 OR [Object] = \u0027DENY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEPTH %\u0027 OR [Object] LIKE \u0027% DEPTH\u0027 OR [Object] = \u0027DEPTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DEREF %\u0027 OR [Object] LIKE \u0027% DEREF\u0027 OR [Object] = \u0027DEREF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DESC %\u0027 OR [Object] LIKE \u0027% DESC\u0027 OR [Object] = \u0027DESC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DESCRIBE %\u0027 OR [Object] LIKE \u0027% DESCRIBE\u0027 OR [Object] = \u0027DESCRIBE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DESCRIPTOR %\u0027 OR [Object] LIKE \u0027% DESCRIPTOR\u0027 OR [Object] = \u0027DESCRIPTOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DESTROY %\u0027 OR [Object] LIKE \u0027% DESTROY\u0027 OR [Object] = \u0027DESTROY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DESTRUCTOR %\u0027 OR [Object] LIKE \u0027% DESTRUCTOR\u0027 OR [Object] = \u0027DESTRUCTOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DETERMINISTIC %\u0027 OR [Object] LIKE \u0027% DETERMINISTIC\u0027 OR [Object] = \u0027DETERMINISTIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DIAGNOSTICS %\u0027 OR [Object] LIKE \u0027% DIAGNOSTICS\u0027 OR [Object] = \u0027DIAGNOSTICS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DICTIONARY %\u0027 OR [Object] LIKE \u0027% DICTIONARY\u0027 OR [Object] = \u0027DICTIONARY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DISCONNECT %\u0027 OR [Object] LIKE \u0027% DISCONNECT\u0027 OR [Object] = \u0027DISCONNECT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DISK %\u0027 OR [Object] LIKE \u0027% DISK\u0027 OR [Object] = \u0027DISK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DISTINCT %\u0027 OR [Object] LIKE \u0027% DISTINCT\u0027 OR [Object] = \u0027DISTINCT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DISTRIBUTED %\u0027 OR [Object] LIKE \u0027% DISTRIBUTED\u0027 OR [Object] = \u0027DISTRIBUTED\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DOMAIN %\u0027 OR [Object] LIKE \u0027% DOMAIN\u0027 OR [Object] = \u0027DOMAIN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DOUBLE %\u0027 OR [Object] LIKE \u0027% DOUBLE\u0027 OR [Object] = \u0027DOUBLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DROP %\u0027 OR [Object] LIKE \u0027% DROP\u0027 OR [Object] = \u0027DROP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DUMMY %\u0027 OR [Object] LIKE \u0027% DUMMY\u0027 OR [Object] = \u0027DUMMY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DUMP %\u0027 OR [Object] LIKE \u0027% DUMP\u0027 OR [Object] = \u0027DUMP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% DYNAMIC %\u0027 OR [Object] LIKE \u0027% DYNAMIC\u0027 OR [Object] = \u0027DYNAMIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EACH %\u0027 OR [Object] LIKE \u0027% EACH\u0027 OR [Object] = \u0027EACH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ELSE %\u0027 OR [Object] LIKE \u0027% ELSE\u0027 OR [Object] = \u0027ELSE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% END %\u0027 OR [Object] LIKE \u0027% END\u0027 OR [Object] = \u0027END\u0027\r\n", "\t\tOR [Object] LIKE \u0027% END-EXEC %\u0027 OR [Object] LIKE \u0027% END-EXEC\u0027 OR [Object] = \u0027END-EXEC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EQUALS %\u0027 OR [Object] LIKE \u0027% EQUALS\u0027 OR [Object] = \u0027EQUALS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ERRLVL %\u0027 OR [Object] LIKE \u0027% ERRLVL\u0027 OR [Object] = \u0027ERRLVL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ESCAPE %\u0027 OR [Object] LIKE \u0027% ESCAPE\u0027 OR [Object] = \u0027ESCAPE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EVERY %\u0027 OR [Object] LIKE \u0027% EVERY\u0027 OR [Object] = \u0027EVERY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXCEPT %\u0027 OR [Object] LIKE \u0027% EXCEPT\u0027 OR [Object] = \u0027EXCEPT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXCEPTION %\u0027 OR [Object] LIKE \u0027% EXCEPTION\u0027 OR [Object] = \u0027EXCEPTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXEC %\u0027 OR [Object] LIKE \u0027% EXEC\u0027 OR [Object] = \u0027EXEC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXECUTE %\u0027 OR [Object] LIKE \u0027% EXECUTE\u0027 OR [Object] = \u0027EXECUTE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXISTS %\u0027 OR [Object] LIKE \u0027% EXISTS\u0027 OR [Object] = \u0027EXISTS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXIT %\u0027 OR [Object] LIKE \u0027% EXIT\u0027 OR [Object] = \u0027EXIT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXTERNAL %\u0027 OR [Object] LIKE \u0027% EXTERNAL\u0027 OR [Object] = \u0027EXTERNAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% EXTRACT %\u0027 OR [Object] LIKE \u0027% EXTRACT\u0027 OR [Object] = \u0027EXTRACT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FALSE %\u0027 OR [Object] LIKE \u0027% FALSE\u0027 OR [Object] = \u0027FALSE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FETCH %\u0027 OR [Object] LIKE \u0027% FETCH\u0027 OR [Object] = \u0027FETCH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FILE %\u0027 OR [Object] LIKE \u0027% FILE\u0027 OR [Object] = \u0027FILE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FILLFACTOR %\u0027 OR [Object] LIKE \u0027% FILLFACTOR\u0027 OR [Object] = \u0027FILLFACTOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FIRST %\u0027 OR [Object] LIKE \u0027% FIRST\u0027 OR [Object] = \u0027FIRST\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FLOAT %\u0027 OR [Object] LIKE \u0027% FLOAT\u0027 OR [Object] = \u0027FLOAT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FOR %\u0027 OR [Object] LIKE \u0027% FOR\u0027 OR [Object] = \u0027FOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FOREIGN %\u0027 OR [Object] LIKE \u0027% FOREIGN\u0027 OR [Object] = \u0027FOREIGN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FORTRAN %\u0027 OR [Object] LIKE \u0027% FORTRAN\u0027 OR [Object] = \u0027FORTRAN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FOUND %\u0027 OR [Object] LIKE \u0027% FOUND\u0027 OR [Object] = \u0027FOUND\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FREE %\u0027 OR [Object] LIKE \u0027% FREE\u0027 OR [Object] = \u0027FREE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FREETEXT %\u0027 OR [Object] LIKE \u0027% FREETEXT\u0027 OR [Object] = \u0027FREETEXT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FREETEXTTABLE %\u0027 OR [Object] LIKE \u0027% FREETEXTTABLE\u0027 OR [Object] = \u0027FREETEXTTABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FROM %\u0027 OR [Object] LIKE \u0027% FROM\u0027 OR [Object] = \u0027FROM\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FULL %\u0027 OR [Object] LIKE \u0027% FULL\u0027 OR [Object] = \u0027FULL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FULLTEXTTABLE %\u0027 OR [Object] LIKE \u0027% FULLTEXTTABLE\u0027 OR [Object] = \u0027FULLTEXTTABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% FUNCTION %\u0027 OR [Object] LIKE \u0027% FUNCTION\u0027 OR [Object] = \u0027FUNCTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GENERAL %\u0027 OR [Object] LIKE \u0027% GENERAL\u0027 OR [Object] = \u0027GENERAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GET %\u0027 OR [Object] LIKE \u0027% GET\u0027 OR [Object] = \u0027GET\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GLOBAL %\u0027 OR [Object] LIKE \u0027% GLOBAL\u0027 OR [Object] = \u0027GLOBAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GO %\u0027 OR [Object] LIKE \u0027% GO\u0027 OR [Object] = \u0027GO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GOTO %\u0027 OR [Object] LIKE \u0027% GOTO\u0027 OR [Object] = \u0027GOTO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GRANT %\u0027 OR [Object] LIKE \u0027% GRANT\u0027 OR [Object] = \u0027GRANT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GROUP %\u0027 OR [Object] LIKE \u0027% GROUP\u0027 OR [Object] = \u0027GROUP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% GROUPING %\u0027 OR [Object] LIKE \u0027% GROUPING\u0027 OR [Object] = \u0027GROUPING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% HAVING %\u0027 OR [Object] LIKE \u0027% HAVING\u0027 OR [Object] = \u0027HAVING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% HOLDLOCK %\u0027 OR [Object] LIKE \u0027% HOLDLOCK\u0027 OR [Object] = \u0027HOLDLOCK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% HOST %\u0027 OR [Object] LIKE \u0027% HOST\u0027 OR [Object] = \u0027HOST\u0027\r\n", "\t\tOR [Object] LIKE \u0027% HOUR %\u0027 OR [Object] LIKE \u0027% HOUR\u0027 OR [Object] = \u0027HOUR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IDENTITY %\u0027 OR [Object] LIKE \u0027% IDENTITY\u0027 OR [Object] = \u0027IDENTITY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IDENTITY_INSERT %\u0027 OR [Object] LIKE \u0027% IDENTITY_INSERT\u0027 OR [Object] = \u0027IDENTITY_INSERT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IDENTITYCOL %\u0027 OR [Object] LIKE \u0027% IDENTITYCOL\u0027 OR [Object] = \u0027IDENTITYCOL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IF %\u0027 OR [Object] LIKE \u0027% IF\u0027 OR [Object] = \u0027IF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IGNORE %\u0027 OR [Object] LIKE \u0027% IGNORE\u0027 OR [Object] = \u0027IGNORE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IMMEDIATE %\u0027 OR [Object] LIKE \u0027% IMMEDIATE\u0027 OR [Object] = \u0027IMMEDIATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IN %\u0027 OR [Object] LIKE \u0027% IN\u0027 OR [Object] = \u0027IN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INCLUDE %\u0027 OR [Object] LIKE \u0027% INCLUDE\u0027 OR [Object] = \u0027INCLUDE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INDEX %\u0027 OR [Object] LIKE \u0027% INDEX\u0027 OR [Object] = \u0027INDEX\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INDICATOR %\u0027 OR [Object] LIKE \u0027% INDICATOR\u0027 OR [Object] = \u0027INDICATOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INITIALIZE %\u0027 OR [Object] LIKE \u0027% INITIALIZE\u0027 OR [Object] = \u0027INITIALIZE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INITIALLY %\u0027 OR [Object] LIKE \u0027% INITIALLY\u0027 OR [Object] = \u0027INITIALLY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INNER %\u0027 OR [Object] LIKE \u0027% INNER\u0027 OR [Object] = \u0027INNER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INOUT %\u0027 OR [Object] LIKE \u0027% INOUT\u0027 OR [Object] = \u0027INOUT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INPUT %\u0027 OR [Object] LIKE \u0027% INPUT\u0027 OR [Object] = \u0027INPUT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INSENSITIVE %\u0027 OR [Object] LIKE \u0027% INSENSITIVE\u0027 OR [Object] = \u0027INSENSITIVE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INSERT %\u0027 OR [Object] LIKE \u0027% INSERT\u0027 OR [Object] = \u0027INSERT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INT %\u0027 OR [Object] LIKE \u0027% INT\u0027 OR [Object] = \u0027INT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INTEGER %\u0027 OR [Object] LIKE \u0027% INTEGER\u0027 OR [Object] = \u0027INTEGER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INTERSECT %\u0027 OR [Object] LIKE \u0027% INTERSECT\u0027 OR [Object] = \u0027INTERSECT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INTERVAL %\u0027 OR [Object] LIKE \u0027% INTERVAL\u0027 OR [Object] = \u0027INTERVAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% INTO %\u0027 OR [Object] LIKE \u0027% INTO\u0027 OR [Object] = \u0027INTO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% IS %\u0027 OR [Object] LIKE \u0027% IS\u0027 OR [Object] = \u0027IS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ISOLATION %\u0027 OR [Object] LIKE \u0027% ISOLATION\u0027 OR [Object] = \u0027ISOLATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ITERATE %\u0027 OR [Object] LIKE \u0027% ITERATE\u0027 OR [Object] = \u0027ITERATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% JOIN %\u0027 OR [Object] LIKE \u0027% JOIN\u0027 OR [Object] = \u0027JOIN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% KEY %\u0027 OR [Object] LIKE \u0027% KEY\u0027 OR [Object] = \u0027KEY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% KILL %\u0027 OR [Object] LIKE \u0027% KILL\u0027 OR [Object] = \u0027KILL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LANGUAGE %\u0027 OR [Object] LIKE \u0027% LANGUAGE\u0027 OR [Object] = \u0027LANGUAGE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LARGE %\u0027 OR [Object] LIKE \u0027% LARGE\u0027 OR [Object] = \u0027LARGE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LAST %\u0027 OR [Object] LIKE \u0027% LAST\u0027 OR [Object] = \u0027LAST\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LATERAL %\u0027 OR [Object] LIKE \u0027% LATERAL\u0027 OR [Object] = \u0027LATERAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LEADING %\u0027 OR [Object] LIKE \u0027% LEADING\u0027 OR [Object] = \u0027LEADING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LEFT %\u0027 OR [Object] LIKE \u0027% LEFT\u0027 OR [Object] = \u0027LEFT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LESS %\u0027 OR [Object] LIKE \u0027% LESS\u0027 OR [Object] = \u0027LESS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LEVEL %\u0027 OR [Object] LIKE \u0027% LEVEL\u0027 OR [Object] = \u0027LEVEL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LIKE %\u0027 OR [Object] LIKE \u0027% LIKE\u0027 OR [Object] = \u0027LIKE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LIMIT %\u0027 OR [Object] LIKE \u0027% LIMIT\u0027 OR [Object] = \u0027LIMIT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LINENO %\u0027 OR [Object] LIKE \u0027% LINENO\u0027 OR [Object] = \u0027LINENO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOAD %\u0027 OR [Object] LIKE \u0027% LOAD\u0027 OR [Object] = \u0027LOAD\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOCAL %\u0027 OR [Object] LIKE \u0027% LOCAL\u0027 OR [Object] = \u0027LOCAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOCALTIME %\u0027 OR [Object] LIKE \u0027% LOCALTIME\u0027 OR [Object] = \u0027LOCALTIME\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOCALTIMESTAMP %\u0027 OR [Object] LIKE \u0027% LOCALTIMESTAMP\u0027 OR [Object] = \u0027LOCALTIMESTAMP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOCATOR %\u0027 OR [Object] LIKE \u0027% LOCATOR\u0027 OR [Object] = \u0027LOCATOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% LOWER %\u0027 OR [Object] LIKE \u0027% LOWER\u0027 OR [Object] = \u0027LOWER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MAP %\u0027 OR [Object] LIKE \u0027% MAP\u0027 OR [Object] = \u0027MAP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MATCH %\u0027 OR [Object] LIKE \u0027% MATCH\u0027 OR [Object] = \u0027MATCH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MAX %\u0027 OR [Object] LIKE \u0027% MAX\u0027 OR [Object] = \u0027MAX\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MIN %\u0027 OR [Object] LIKE \u0027% MIN\u0027 OR [Object] = \u0027MIN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MINUTE %\u0027 OR [Object] LIKE \u0027% MINUTE\u0027 OR [Object] = \u0027MINUTE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MODIFIES %\u0027 OR [Object] LIKE \u0027% MODIFIES\u0027 OR [Object] = \u0027MODIFIES\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MODIFY %\u0027 OR [Object] LIKE \u0027% MODIFY\u0027 OR [Object] = \u0027MODIFY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MODULE %\u0027 OR [Object] LIKE \u0027% MODULE\u0027 OR [Object] = \u0027MODULE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% MONTH %\u0027 OR [Object] LIKE \u0027% MONTH\u0027 OR [Object] = \u0027MONTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NAMES %\u0027 OR [Object] LIKE \u0027% NAMES\u0027 OR [Object] = \u0027NAMES\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NATIONAL %\u0027 OR [Object] LIKE \u0027% NATIONAL\u0027 OR [Object] = \u0027NATIONAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NATURAL %\u0027 OR [Object] LIKE \u0027% NATURAL\u0027 OR [Object] = \u0027NATURAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NCHAR %\u0027 OR [Object] LIKE \u0027% NCHAR\u0027 OR [Object] = \u0027NCHAR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NCLOB %\u0027 OR [Object] LIKE \u0027% NCLOB\u0027 OR [Object] = \u0027NCLOB\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NEW %\u0027 OR [Object] LIKE \u0027% NEW\u0027 OR [Object] = \u0027NEW\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NEXT %\u0027 OR [Object] LIKE \u0027% NEXT\u0027 OR [Object] = \u0027NEXT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NO %\u0027 OR [Object] LIKE \u0027% NO\u0027 OR [Object] = \u0027NO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NOCHECK %\u0027 OR [Object] LIKE \u0027% NOCHECK\u0027 OR [Object] = \u0027NOCHECK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NONCLUSTERED %\u0027 OR [Object] LIKE \u0027% NONCLUSTERED\u0027 OR [Object] = \u0027NONCLUSTERED\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NONE %\u0027 OR [Object] LIKE \u0027% NONE\u0027 OR [Object] = \u0027NONE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NOT %\u0027 OR [Object] LIKE \u0027% NOT\u0027 OR [Object] = \u0027NOT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NULL %\u0027 OR [Object] LIKE \u0027% NULL\u0027 OR [Object] = \u0027NULL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NULLIF %\u0027 OR [Object] LIKE \u0027% NULLIF\u0027 OR [Object] = \u0027NULLIF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% NUMERIC %\u0027 OR [Object] LIKE \u0027% NUMERIC\u0027 OR [Object] = \u0027NUMERIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OBJECT %\u0027 OR [Object] LIKE \u0027% OBJECT\u0027 OR [Object] = \u0027OBJECT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OCTET_LENGTH %\u0027 OR [Object] LIKE \u0027% OCTET_LENGTH\u0027 OR [Object] = \u0027OCTET_LENGTH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OF %\u0027 OR [Object] LIKE \u0027% OF\u0027 OR [Object] = \u0027OF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OFF %\u0027 OR [Object] LIKE \u0027% OFF\u0027 OR [Object] = \u0027OFF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OFFSETS %\u0027 OR [Object] LIKE \u0027% OFFSETS\u0027 OR [Object] = \u0027OFFSETS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OLD %\u0027 OR [Object] LIKE \u0027% OLD\u0027 OR [Object] = \u0027OLD\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ON %\u0027 OR [Object] LIKE \u0027% ON\u0027 OR [Object] = \u0027ON\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ONLY %\u0027 OR [Object] LIKE \u0027% ONLY\u0027 OR [Object] = \u0027ONLY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPEN %\u0027 OR [Object] LIKE \u0027% OPEN\u0027 OR [Object] = \u0027OPEN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPENDATASOURCE %\u0027 OR [Object] LIKE \u0027% OPENDATASOURCE\u0027 OR [Object] = \u0027OPENDATASOURCE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPENQUERY %\u0027 OR [Object] LIKE \u0027% OPENQUERY\u0027 OR [Object] = \u0027OPENQUERY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPENROWSET %\u0027 OR [Object] LIKE \u0027% OPENROWSET\u0027 OR [Object] = \u0027OPENROWSET\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPENXML %\u0027 OR [Object] LIKE \u0027% OPENXML\u0027 OR [Object] = \u0027OPENXML\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPERATION %\u0027 OR [Object] LIKE \u0027% OPERATION\u0027 OR [Object] = \u0027OPERATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OPTION %\u0027 OR [Object] LIKE \u0027% OPTION\u0027 OR [Object] = \u0027OPTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OR %\u0027 OR [Object] LIKE \u0027% OR\u0027 OR [Object] = \u0027OR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ORDER %\u0027 OR [Object] LIKE \u0027% ORDER\u0027 OR [Object] = \u0027ORDER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ORDINALITY %\u0027 OR [Object] LIKE \u0027% ORDINALITY\u0027 OR [Object] = \u0027ORDINALITY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OUT %\u0027 OR [Object] LIKE \u0027% OUT\u0027 OR [Object] = \u0027OUT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OUTER %\u0027 OR [Object] LIKE \u0027% OUTER\u0027 OR [Object] = \u0027OUTER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OUTPUT %\u0027 OR [Object] LIKE \u0027% OUTPUT\u0027 OR [Object] = \u0027OUTPUT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OVER %\u0027 OR [Object] LIKE \u0027% OVER\u0027 OR [Object] = \u0027OVER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% OVERLAPS %\u0027 OR [Object] LIKE \u0027% OVERLAPS\u0027 OR [Object] = \u0027OVERLAPS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PAD %\u0027 OR [Object] LIKE \u0027% PAD\u0027 OR [Object] = \u0027PAD\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PARAMETER %\u0027 OR [Object] LIKE \u0027% PARAMETER\u0027 OR [Object] = \u0027PARAMETER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PARAMETERS %\u0027 OR [Object] LIKE \u0027% PARAMETERS\u0027 OR [Object] = \u0027PARAMETERS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PARTIAL %\u0027 OR [Object] LIKE \u0027% PARTIAL\u0027 OR [Object] = \u0027PARTIAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PASCAL %\u0027 OR [Object] LIKE \u0027% PASCAL\u0027 OR [Object] = \u0027PASCAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PATH %\u0027 OR [Object] LIKE \u0027% PATH\u0027 OR [Object] = \u0027PATH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PERCENT %\u0027 OR [Object] LIKE \u0027% PERCENT\u0027 OR [Object] = \u0027PERCENT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PLAN %\u0027 OR [Object] LIKE \u0027% PLAN\u0027 OR [Object] = \u0027PLAN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% POSITION %\u0027 OR [Object] LIKE \u0027% POSITION\u0027 OR [Object] = \u0027POSITION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% POSTFIX %\u0027 OR [Object] LIKE \u0027% POSTFIX\u0027 OR [Object] = \u0027POSTFIX\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRECISION %\u0027 OR [Object] LIKE \u0027% PRECISION\u0027 OR [Object] = \u0027PRECISION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PREFIX %\u0027 OR [Object] LIKE \u0027% PREFIX\u0027 OR [Object] = \u0027PREFIX\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PREORDER %\u0027 OR [Object] LIKE \u0027% PREORDER\u0027 OR [Object] = \u0027PREORDER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PREPARE %\u0027 OR [Object] LIKE \u0027% PREPARE\u0027 OR [Object] = \u0027PREPARE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRESERVE %\u0027 OR [Object] LIKE \u0027% PRESERVE\u0027 OR [Object] = \u0027PRESERVE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRIMARY %\u0027 OR [Object] LIKE \u0027% PRIMARY\u0027 OR [Object] = \u0027PRIMARY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRINT %\u0027 OR [Object] LIKE \u0027% PRINT\u0027 OR [Object] = \u0027PRINT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRIOR %\u0027 OR [Object] LIKE \u0027% PRIOR\u0027 OR [Object] = \u0027PRIOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PRIVILEGES %\u0027 OR [Object] LIKE \u0027% PRIVILEGES\u0027 OR [Object] = \u0027PRIVILEGES\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PROC %\u0027 OR [Object] LIKE \u0027% PROC\u0027 OR [Object] = \u0027PROC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PROCEDURE %\u0027 OR [Object] LIKE \u0027% PROCEDURE\u0027 OR [Object] = \u0027PROCEDURE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% PUBLIC %\u0027 OR [Object] LIKE \u0027% PUBLIC\u0027 OR [Object] = \u0027PUBLIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RAISERROR %\u0027 OR [Object] LIKE \u0027% RAISERROR\u0027 OR [Object] = \u0027RAISERROR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% READ %\u0027 OR [Object] LIKE \u0027% READ\u0027 OR [Object] = \u0027READ\u0027\r\n", "\t\tOR [Object] LIKE \u0027% READS %\u0027 OR [Object] LIKE \u0027% READS\u0027 OR [Object] = \u0027READS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% READTEXT %\u0027 OR [Object] LIKE \u0027% READTEXT\u0027 OR [Object] = \u0027READTEXT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REAL %\u0027 OR [Object] LIKE \u0027% REAL\u0027 OR [Object] = \u0027REAL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RECONFIGURE %\u0027 OR [Object] LIKE \u0027% RECONFIGURE\u0027 OR [Object] = \u0027RECONFIGURE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RECURSIVE %\u0027 OR [Object] LIKE \u0027% RECURSIVE\u0027 OR [Object] = \u0027RECURSIVE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REF %\u0027 OR [Object] LIKE \u0027% REF\u0027 OR [Object] = \u0027REF\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REFERENCES %\u0027 OR [Object] LIKE \u0027% REFERENCES\u0027 OR [Object] = \u0027REFERENCES\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REFERENCING %\u0027 OR [Object] LIKE \u0027% REFERENCING\u0027 OR [Object] = \u0027REFERENCING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RELATIVE %\u0027 OR [Object] LIKE \u0027% RELATIVE\u0027 OR [Object] = \u0027RELATIVE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REPLICATION %\u0027 OR [Object] LIKE \u0027% REPLICATION\u0027 OR [Object] = \u0027REPLICATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RESTORE %\u0027 OR [Object] LIKE \u0027% RESTORE\u0027 OR [Object] = \u0027RESTORE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RESTRICT %\u0027 OR [Object] LIKE \u0027% RESTRICT\u0027 OR [Object] = \u0027RESTRICT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RESULT %\u0027 OR [Object] LIKE \u0027% RESULT\u0027 OR [Object] = \u0027RESULT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RETURN %\u0027 OR [Object] LIKE \u0027% RETURN\u0027 OR [Object] = \u0027RETURN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RETURNS %\u0027 OR [Object] LIKE \u0027% RETURNS\u0027 OR [Object] = \u0027RETURNS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% REVOKE %\u0027 OR [Object] LIKE \u0027% REVOKE\u0027 OR [Object] = \u0027REVOKE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RIGHT %\u0027 OR [Object] LIKE \u0027% RIGHT\u0027 OR [Object] = \u0027RIGHT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROLE %\u0027 OR [Object] LIKE \u0027% ROLE\u0027 OR [Object] = \u0027ROLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROLLBACK %\u0027 OR [Object] LIKE \u0027% ROLLBACK\u0027 OR [Object] = \u0027ROLLBACK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROLLUP %\u0027 OR [Object] LIKE \u0027% ROLLUP\u0027 OR [Object] = \u0027ROLLUP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROUTINE %\u0027 OR [Object] LIKE \u0027% ROUTINE\u0027 OR [Object] = \u0027ROUTINE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROW %\u0027 OR [Object] LIKE \u0027% ROW\u0027 OR [Object] = \u0027ROW\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROWCOUNT %\u0027 OR [Object] LIKE \u0027% ROWCOUNT\u0027 OR [Object] = \u0027ROWCOUNT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROWGUIDCOL %\u0027 OR [Object] LIKE \u0027% ROWGUIDCOL\u0027 OR [Object] = \u0027ROWGUIDCOL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ROWS %\u0027 OR [Object] LIKE \u0027% ROWS\u0027 OR [Object] = \u0027ROWS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% RULE %\u0027 OR [Object] LIKE \u0027% RULE\u0027 OR [Object] = \u0027RULE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SAVE %\u0027 OR [Object] LIKE \u0027% SAVE\u0027 OR [Object] = \u0027SAVE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SAVEPOINT %\u0027 OR [Object] LIKE \u0027% SAVEPOINT\u0027 OR [Object] = \u0027SAVEPOINT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SCHEMA %\u0027 OR [Object] LIKE \u0027% SCHEMA\u0027 OR [Object] = \u0027SCHEMA\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SCOPE %\u0027 OR [Object] LIKE \u0027% SCOPE\u0027 OR [Object] = \u0027SCOPE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SCROLL %\u0027 OR [Object] LIKE \u0027% SCROLL\u0027 OR [Object] = \u0027SCROLL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SEARCH %\u0027 OR [Object] LIKE \u0027% SEARCH\u0027 OR [Object] = \u0027SEARCH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SECOND %\u0027 OR [Object] LIKE \u0027% SECOND\u0027 OR [Object] = \u0027SECOND\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SECTION %\u0027 OR [Object] LIKE \u0027% SECTION\u0027 OR [Object] = \u0027SECTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SELECT %\u0027 OR [Object] LIKE \u0027% SELECT\u0027 OR [Object] = \u0027SELECT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SEQUENCE %\u0027 OR [Object] LIKE \u0027% SEQUENCE\u0027 OR [Object] = \u0027SEQUENCE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SESSION %\u0027 OR [Object] LIKE \u0027% SESSION\u0027 OR [Object] = \u0027SESSION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SESSION_USER %\u0027 OR [Object] LIKE \u0027% SESSION_USER\u0027 OR [Object] = \u0027SESSION_USER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SET %\u0027 OR [Object] LIKE \u0027% SET\u0027 OR [Object] = \u0027SET\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SETS %\u0027 OR [Object] LIKE \u0027% SETS\u0027 OR [Object] = \u0027SETS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SETUSER %\u0027 OR [Object] LIKE \u0027% SETUSER\u0027 OR [Object] = \u0027SETUSER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SHUTDOWN %\u0027 OR [Object] LIKE \u0027% SHUTDOWN\u0027 OR [Object] = \u0027SHUTDOWN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SIZE %\u0027 OR [Object] LIKE \u0027% SIZE\u0027 OR [Object] = \u0027SIZE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SMALLINT %\u0027 OR [Object] LIKE \u0027% SMALLINT\u0027 OR [Object] = \u0027SMALLINT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SOME %\u0027 OR [Object] LIKE \u0027% SOME\u0027 OR [Object] = \u0027SOME\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SPACE %\u0027 OR [Object] LIKE \u0027% SPACE\u0027 OR [Object] = \u0027SPACE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SPECIFIC %\u0027 OR [Object] LIKE \u0027% SPECIFIC\u0027 OR [Object] = \u0027SPECIFIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SPECIFICTYPE %\u0027 OR [Object] LIKE \u0027% SPECIFICTYPE\u0027 OR [Object] = \u0027SPECIFICTYPE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQL %\u0027 OR [Object] LIKE \u0027% SQL\u0027 OR [Object] = \u0027SQL\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLCA %\u0027 OR [Object] LIKE \u0027% SQLCA\u0027 OR [Object] = \u0027SQLCA\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLCODE %\u0027 OR [Object] LIKE \u0027% SQLCODE\u0027 OR [Object] = \u0027SQLCODE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLERROR %\u0027 OR [Object] LIKE \u0027% SQLERROR\u0027 OR [Object] = \u0027SQLERROR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLEXCEPTION %\u0027 OR [Object] LIKE \u0027% SQLEXCEPTION\u0027 OR [Object] = \u0027SQLEXCEPTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLSTATE %\u0027 OR [Object] LIKE \u0027% SQLSTATE\u0027 OR [Object] = \u0027SQLSTATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SQLWARNING %\u0027 OR [Object] LIKE \u0027% SQLWARNING\u0027 OR [Object] = \u0027SQLWARNING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% START %\u0027 OR [Object] LIKE \u0027% START\u0027 OR [Object] = \u0027START\u0027\r\n", "\t\tOR [Object] LIKE \u0027% STATE %\u0027 OR [Object] LIKE \u0027% STATE\u0027 OR [Object] = \u0027STATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% STATEMENT %\u0027 OR [Object] LIKE \u0027% STATEMENT\u0027 OR [Object] = \u0027STATEMENT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% STATIC %\u0027 OR [Object] LIKE \u0027% STATIC\u0027 OR [Object] = \u0027STATIC\u0027\r\n", "\t\tOR [Object] LIKE \u0027% STATISTICS %\u0027 OR [Object] LIKE \u0027% STATISTICS\u0027 OR [Object] = \u0027STATISTICS\u0027\r\n", "\t\tOR [Object] LIKE \u0027% STRUCTURE %\u0027 OR [Object] LIKE \u0027% STRUCTURE\u0027 OR [Object] = \u0027STRUCTURE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SUBSTRING %\u0027 OR [Object] LIKE \u0027% SUBSTRING\u0027 OR [Object] = \u0027SUBSTRING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SUM %\u0027 OR [Object] LIKE \u0027% SUM\u0027 OR [Object] = \u0027SUM\u0027\r\n", "\t\tOR [Object] LIKE \u0027% SYSTEM_USER %\u0027 OR [Object] LIKE \u0027% SYSTEM_USER\u0027 OR [Object] = \u0027SYSTEM_USER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TABLE %\u0027 OR [Object] LIKE \u0027% TABLE\u0027 OR [Object] = \u0027TABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TEMPORARY %\u0027 OR [Object] LIKE \u0027% TEMPORARY\u0027 OR [Object] = \u0027TEMPORARY\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TERMINATE %\u0027 OR [Object] LIKE \u0027% TERMINATE\u0027 OR [Object] = \u0027TERMINATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TEXTSIZE %\u0027 OR [Object] LIKE \u0027% TEXTSIZE\u0027 OR [Object] = \u0027TEXTSIZE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% THAN %\u0027 OR [Object] LIKE \u0027% THAN\u0027 OR [Object] = \u0027THAN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% THEN %\u0027 OR [Object] LIKE \u0027% THEN\u0027 OR [Object] = \u0027THEN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TIME %\u0027 OR [Object] LIKE \u0027% TIME\u0027 OR [Object] = \u0027TIME\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TIMESTAMP %\u0027 OR [Object] LIKE \u0027% TIMESTAMP\u0027 OR [Object] = \u0027TIMESTAMP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TIMEZONE_HOUR %\u0027 OR [Object] LIKE \u0027% TIMEZONE_HOUR\u0027 OR [Object] = \u0027TIMEZONE_HOUR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TIMEZONE_MINUTE %\u0027 OR [Object] LIKE \u0027% TIMEZONE_MINUTE\u0027 OR [Object] = \u0027TIMEZONE_MINUTE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TO %\u0027 OR [Object] LIKE \u0027% TO\u0027 OR [Object] = \u0027TO\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TOP %\u0027 OR [Object] LIKE \u0027% TOP\u0027 OR [Object] = \u0027TOP\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRAILING %\u0027 OR [Object] LIKE \u0027% TRAILING\u0027 OR [Object] = \u0027TRAILING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRAN %\u0027 OR [Object] LIKE \u0027% TRAN\u0027 OR [Object] = \u0027TRAN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRANSACTION %\u0027 OR [Object] LIKE \u0027% TRANSACTION\u0027 OR [Object] = \u0027TRANSACTION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRANSLATE %\u0027 OR [Object] LIKE \u0027% TRANSLATE\u0027 OR [Object] = \u0027TRANSLATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRANSLATION %\u0027 OR [Object] LIKE \u0027% TRANSLATION\u0027 OR [Object] = \u0027TRANSLATION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TREAT %\u0027 OR [Object] LIKE \u0027% TREAT\u0027 OR [Object] = \u0027TREAT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRIGGER %\u0027 OR [Object] LIKE \u0027% TRIGGER\u0027 OR [Object] = \u0027TRIGGER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRIM %\u0027 OR [Object] LIKE \u0027% TRIM\u0027 OR [Object] = \u0027TRIM\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRUE %\u0027 OR [Object] LIKE \u0027% TRUE\u0027 OR [Object] = \u0027TRUE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% TRUNCATE %\u0027 OR [Object] LIKE \u0027% TRUNCATE\u0027 OR [Object] = \u0027TRUNCATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UNDER %\u0027 OR [Object] LIKE \u0027% UNDER\u0027 OR [Object] = \u0027UNDER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UNION %\u0027 OR [Object] LIKE \u0027% UNION\u0027 OR [Object] = \u0027UNION\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UNIQUE %\u0027 OR [Object] LIKE \u0027% UNIQUE\u0027 OR [Object] = \u0027UNIQUE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UNKNOWN %\u0027 OR [Object] LIKE \u0027% UNKNOWN\u0027 OR [Object] = \u0027UNKNOWN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UNNEST %\u0027 OR [Object] LIKE \u0027% UNNEST\u0027 OR [Object] = \u0027UNNEST\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UPDATE %\u0027 OR [Object] LIKE \u0027% UPDATE\u0027 OR [Object] = \u0027UPDATE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UPDATETEXT %\u0027 OR [Object] LIKE \u0027% UPDATETEXT\u0027 OR [Object] = \u0027UPDATETEXT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% UPPER %\u0027 OR [Object] LIKE \u0027% UPPER\u0027 OR [Object] = \u0027UPPER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% USAGE %\u0027 OR [Object] LIKE \u0027% USAGE\u0027 OR [Object] = \u0027USAGE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% USE %\u0027 OR [Object] LIKE \u0027% USE\u0027 OR [Object] = \u0027USE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% USER %\u0027 OR [Object] LIKE \u0027% USER\u0027 OR [Object] = \u0027USER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% USING %\u0027 OR [Object] LIKE \u0027% USING\u0027 OR [Object] = \u0027USING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VALUE %\u0027 OR [Object] LIKE \u0027% VALUE\u0027 OR [Object] = \u0027VALUE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VALUES %\u0027 OR [Object] LIKE \u0027% VALUES\u0027 OR [Object] = \u0027VALUES\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VARCHAR %\u0027 OR [Object] LIKE \u0027% VARCHAR\u0027 OR [Object] = \u0027VARCHAR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VARIABLE %\u0027 OR [Object] LIKE \u0027% VARIABLE\u0027 OR [Object] = \u0027VARIABLE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VARYING %\u0027 OR [Object] LIKE \u0027% VARYING\u0027 OR [Object] = \u0027VARYING\u0027\r\n", "\t\tOR [Object] LIKE \u0027% VIEW %\u0027 OR [Object] LIKE \u0027% VIEW\u0027 OR [Object] = \u0027VIEW\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WAITFOR %\u0027 OR [Object] LIKE \u0027% WAITFOR\u0027 OR [Object] = \u0027WAITFOR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WHEN %\u0027 OR [Object] LIKE \u0027% WHEN\u0027 OR [Object] = \u0027WHEN\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WHENEVER %\u0027 OR [Object] LIKE \u0027% WHENEVER\u0027 OR [Object] = \u0027WHENEVER\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WHERE %\u0027 OR [Object] LIKE \u0027% WHERE\u0027 OR [Object] = \u0027WHERE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WHILE %\u0027 OR [Object] LIKE \u0027% WHILE\u0027 OR [Object] = \u0027WHILE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WITH %\u0027 OR [Object] LIKE \u0027% WITH\u0027 OR [Object] = \u0027WITH\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WITHOUT %\u0027 OR [Object] LIKE \u0027% WITHOUT\u0027 OR [Object] = \u0027WITHOUT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WORK %\u0027 OR [Object] LIKE \u0027% WORK\u0027 OR [Object] = \u0027WORK\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WRITE %\u0027 OR [Object] LIKE \u0027% WRITE\u0027 OR [Object] = \u0027WRITE\u0027\r\n", "\t\tOR [Object] LIKE \u0027% WRITETEXT %\u0027 OR [Object] LIKE \u0027% WRITETEXT\u0027 OR [Object] = \u0027WRITETEXT\u0027\r\n", "\t\tOR [Object] LIKE \u0027% YEAR %\u0027 OR [Object] LIKE \u0027% YEAR\u0027 OR [Object] = \u0027YEAR\u0027\r\n", "\t\tOR [Object] LIKE \u0027% ZONE %\u0027 OR [Object] LIKE \u0027% ZONE\u0027 OR [Object] = \u0027ZONE\u0027);\r\n", "\t/* https://docs.microsoft.com/sql/t-sql/statements/create-function-transact-sql*/\r\n", "\tINSERT INTO #tmpfinalobjectnames\r\n", "\tSELECT 5, [DBName], [schemaName], [Object], [Col], type_desc, NULL\r\n", "\tFROM #tmpobjectnames\r\n", "\tWHERE [type] IN (\u0027FN\u0027,\u0027FS\u0027,\u0027TF\u0027,\u0027IF\u0027) AND [Object] LIKE \u0027fn[_]%\u0027\r\n", "\t\tAND [Object] NOT IN (\u0027fn_diagram_objects\u0027);\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM #tmpfinalobjectnames) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Naming_checks\u0027 AS [Category], \u0027Object_Naming_Convention\u0027 AS [Check], \u0027[WARNING: Reserved words or special characters have been found in object names]\u0027 AS [Deviation]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Naming_checks\u0027 AS [Category], \u0027Object_Naming_Convention\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM #tmpfinalobjectnames) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Naming_checks\u0027 AS [Category], \u0027Object_Naming_Convention\u0027 AS [Check],\r\n", "\t\t\tCASE [Deviation] WHEN 1 THEN \u0027[sp_ as prefix for stored procedures]\u0027\r\n", "\t\t\tWHEN 2 THEN \u0027[Special character as part of object name]\u0027\r\n", "\t\t\tWHEN 3 THEN \u0027[Special character as part of column name]\u0027\r\n", "\t\t\tWHEN 4 THEN \u0027[Reserved words as part of object name]\u0027\r\n", "\t\t\tWHEN 5 THEN \u0027[fn_ as prefix for user defined functions]\u0027\r\n", "\t\t\tEND AS [Deviation],\r\n", "\t\t\t[DBName] AS [Database_Name], [schemaName] AS [Schema_Name], [Object] AS [Object_Name], QUOTENAME([Col]) AS [Col], [type_desc] AS [Object_Type]\r\n", "\t\tFROM #tmpfinalobjectnames\r\n", "\t\tORDER BY [Deviation], type_desc, [DBName], [schemaName], [Object];\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Security Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "c9ea9d9f-3f4b-46fc-b94c-90742853b852", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### Password check subsection\r\n" ], "metadata": { "azdata_cell_guid": "8a1ed288-04fc-41fd-b021-77fd31e2c5bc" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Password check\u0027, 10, 1) WITH NOWAIT\r\n", "\tDECLARE @passwords TABLE ([Deviation] VARCHAR(15),\r\n", "\t\t[Name] sysname,\r\n", "\t\t[CreateDate] DATETIME)\r\n", "\tDECLARE @word TABLE (word NVARCHAR(50))\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(0)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(1)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(12)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(123)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(1234)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(12345)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(123456)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(1234567)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(12345678)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(123456789)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(1234567890)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(11111)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(111111)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(1111111)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(11111111)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(21)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(4321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(54321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(654321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(7654321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(87654321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(987654321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(0987654321)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027pwd\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027Password\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027password\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027P@ssw0rd\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027p@ssw0rd\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027Teste\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027teste\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027Test\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027test\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027\u0027)\r\n", "\tINSERT INTO @word\r\n", "\tvalues\r\n", "\t\t(\u0027p@wd\u0027)\r\n", "\tINSERT INTO @passwords\r\n", "\t\t\t\tSELECT DISTINCT \u0027Weak_Password\u0027 AS Deviation, RTRIM(s.name) AS [Name], createdate AS [CreateDate]\r\n", "\t\tFROM @word d\r\n", "\t\t\tINNER JOIN master.sys.syslogins s ON PWDCOMPARE(RTRIM(RTRIM(d.word)), s.[password]) = 1\r\n", "\tUNION ALL\r\n", "\t\tSELECT \u0027NULL_Passwords\u0027 AS Deviation, RTRIM(name) AS [Name], createdate AS [CreateDate]\r\n", "\t\tFROM master.sys.syslogins\r\n", "\t\tWHERE [password] IS NULL\r\n", "\t\t\tAND isntname = 0\r\n", "\t\t\tAND name NOT IN (\u0027MSCRMSqlClrLogin\u0027,\u0027##MS_SmoExtendedSigningCertificate##\u0027,\u0027##MS_PolicySigningCertificate##\u0027,\u0027##MS_SQLResourceSigningCertificate##\u0027,\u0027##MS_SQLReplicationSigningCertificate##\u0027,\u0027##MS_SQLAuthenticatorCertificate##\u0027,\u0027##MS_AgentSigningCertificate##\u0027,\u0027##MS_SQLEnableSystemAssemblyLoadingUser##\u0027)\r\n", "\tUNION ALL\r\n", "\t\tSELECT DISTINCT \u0027Name=Password\u0027 AS Deviation, RTRIM(s.name) AS [Name], createdate AS [CreateDate]\r\n", "\t\tFROM master.sys.syslogins s\r\n", "\t\tWHERE PWDCOMPARE(RTRIM(RTRIM(s.name)), s.[password]) = 1\r\n", "\tORDER BY [Deviation], [Name]\r\n", "\tIF (SELECT COUNT([Deviation])\r\n", "\tFROM @passwords) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Security_checks\u0027 AS [Category], \u0027Password_checks\u0027 AS [Check], \u0027[WARNING: Some user logins have weak passwords. Please review these as soon as possible]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Security_checks\u0027 AS [Category], \u0027Password_checks\u0027 AS [Information], [Deviation], [Name], [CreateDate]\r\n", "\t\tFROM @passwords\r\n", "\t\tORDER BY [Deviation], [Name]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Security_checks\u0027 AS [Category], \u0027Password_checks\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\tEND;\r\n", "\tRAISERROR (N\u0027|-Starting Maintenance and Monitoring Checks\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "d3a95bec-0917-45fd-9fab-1b4bc75622df", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "--### SQL Agent alerts for severe errors subsection\r\n" ], "metadata": { "azdata_cell_guid": "517684de-4d12-427c-bb3b-d8680543724b" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting SQL Agent alerts for severe errors\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT [perm]\r\n", "\t\tFROM tempdb.dbo.permstbl_msdb\r\n", "\t\tWHERE [id] = 1) = 0 AND (SELECT [perm]\r\n", "\t\tFROM tempdb.dbo.permstbl_msdb\r\n", "\t\tWHERE [id] = 2) = 0\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: If not sysadmin, then you must be a member of MSDB SQLAgentOperatorRole role, or have SELECT permission on the sysalerts table in MSDB. Bypassing check]\u0027, 16, 1, N\u0027msdbperms\u0027)\r\n", "--RETURN\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_10\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (825,833,855,856,3452,3619,17179,17883,17884,17887,17888,17890,28036) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (825,833,855,856,3452,3619,17179,17883,17884,17887,17888,17890,28036) OR severity = 10\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_16\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (2508,2511,3271,5228,5229,5242,5243,5250,5901,17130,17300) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (610,2508,2511,3271,5228,5229,5242,5243,5250,5901,8621,17065,17066,17067,17130,17300) OR severity = 16\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_17\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (802,845,1101,1105,1121,1214,9002) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (802,845,1101,1105,1121,1214,8642,9002) OR severity = 17\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_19\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (701) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (701) OR severity = 19\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_20\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (3624) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (3624) OR severity = 20\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_21\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (605) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (605) OR severity = 21\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_22\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (5180,8966) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (5180,8966) OR severity = 22\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_23\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (5572,9100) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (5572,9100) OR severity = 23\r\n", "\t\tUNION ALL\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts_Severity_24\u0027 AS [Check], CASE WHEN COUNT([name]) > 0 THEN \u0027[OK]\u0027 ELSE \u0027[WARNING: Important errors (823,824,832) are not raising alerts. Please review the need to create these]\u0027 END AS [Deviation]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE [message_id] IN (823,824,832) OR severity = 24\r\n", "\t\tIF (SELECT COUNT([name])\r\n", "\t\tFROM msdb.dbo.sysalerts\r\n", "\t\tWHERE ([message_id] IN (825,833,855,856,3452,3619,17179,17883,17884,17887,17888,17890,28036, -- Sev 10\r\n", "\t\t\t610,2508,2511,3271,5228,5229,5242,5243,5250,5901,8621,17065,17066,17067,17130,17300, -- Sev 16 \r\n", "\t\t\t802,845,1101,1105,1121,1214,8642,9002, -- Sev 17\r\n", "\t\t\t701, -- Sev 19\r\n", "\t\t\t3624, -- Sev 20\r\n", "\t\t\t605, -- Sev 21\r\n", "\t\t\t5180,8966, -- Sev 22\r\n", "\t\t\t5572,9100, -- Sev 23\r\n", "\t\t\t823,824,832 -- Sev 24\r\n", "\t\t\t) OR [severity] >= 17)) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Agent_Alerts\u0027 AS [Information], QUOTENAME([name]) AS [Configured_Alert], CASE WHEN [enabled] = 1 THEN \u0027Enabled\u0027 ELSE \u0027Disabled\u0027 END AS [Alert_Status], [event_source] AS [Event_Source], [message_id], [severity]\r\n", "\t\t\tFROM msdb.dbo.sysalerts\r\n", "\t\t\tWHERE ([message_id] IN (825,833,855,856,3452,3619,17179,17883,17884,17887,17888,17890,28036, -- Sev 10\r\n", "\t\t\t610,2508,2511,3271,5228,5229,5242,5243,5250,5901,8621,17065,17066,17067,17130,17300, -- Sev 16 \r\n", "\t\t\t802,845,1101,1105,1121,1214,8642,9002, -- Sev 17\r\n", "\t\t\t701, -- Sev 19\r\n", "\t\t\t3624, -- Sev 20\r\n", "\t\t\t605, -- Sev 21\r\n", "\t\t\t5180,8966, -- Sev 22\r\n", "\t\t\t5572,9100, -- Sev 23\r\n", "\t\t\t823,824,832 -- Sev 24\r\n", "\t\t\t) OR [severity] >= 17);\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "00b9aeae-4d75-4c26-9f84-e1b4aa91c622", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### DBCC CHECKDB, Direct Catalog Updates and Data Purity subsection\r\n" ], "metadata": { "azdata_cell_guid": "a2a01457-9d88-41b2-8eb8-ce1e1dbb3848" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting DBCC CHECKDB, Direct Catalog Updates and Data Purity\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#output_dbinfo\u0027))\r\n", "DROP TABLE #output_dbinfo;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#output_dbinfo\u0027))\r\n", "CREATE TABLE #output_dbinfo\r\n", "\t(\r\n", "\t\tParentObject NVARCHAR(255),\r\n", "\t\t[Object] NVARCHAR(255),\r\n", "\t\tField NVARCHAR(255),\r\n", "\t\t[value] NVARCHAR(255)\r\n", "\t)\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbinfo\u0027))\r\n", "DROP TABLE #dbinfo;\r\n", "\tIF NOT EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbinfo\u0027))\r\n", "CREATE TABLE #dbinfo\r\n", "\t(\r\n", "\t\trowid int IDENTITY(1,1) PRIMARY KEY CLUSTERED,\r\n", "\t\tdbname NVARCHAR(255),\r\n", "\t\tlst_known_checkdb DATETIME NULL,\r\n", "\t\tupdSysCatalog DATETIME NULL,\r\n", "\t\tdbi_createVersion int NULL,\r\n", "\t\tdbi_dbccFlags int NULL\r\n", "\t)\r\n", "\tIF (ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1)\r\n", "BEGIN\r\n", "\t--DECLARE @dbname NVARCHAR(255);\r\n", "\t\tDECLARE @dbcc bit, @catupd bit, @purity bit;\r\n", "\t\tDECLARE curDBs CURSOR FAST_FORWARD FOR SELECT [name]\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE is_read_only = 0 AND [state] = 0\r\n", "\t\tOPEN curDBs\r\n", "\t\tFETCH NEXT FROM curDBs INTO @dbname\r\n", "\t\tWHILE (@@FETCH_STATUS = 0)\r\n", "\tBEGIN\r\n", "\t\t\tIF (SELECT CHARINDEX(CHAR(39), @dbname)) > 0\r\n", "\t\t\t\tOR (SELECT CHARINDEX(CHAR(45), @dbname)) > 0\r\n", "\t\t\t\tOR (SELECT CHARINDEX(CHAR(47), @dbname)) > 0\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT @ErrorMessage = \u0027 |-Skipping Database ID \u0027 + CONVERT(NVARCHAR, DB_ID(QUOTENAME(@dbname))) + \u0027 due to possible SQL Injection\u0027\r\n", "\t\t\t\tRAISERROR (@ErrorMessage, 10, 1) WITH NOWAIT;\r\n", "\t\t\tEND\r\n", "\t\tELSE\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSET @dbname = RTRIM(LTRIM(@dbname))\r\n", "\t\t\t\tSET @query = N\u0027DBCC DBINFO(N\u0027\u0027\u0027 + @dbname + N\u0027\u0027\u0027) WITH TABLERESULTS, NO_INFOMSGS\u0027\r\n", "\t\t\t\tINSERT INTO #output_dbinfo\r\n", "\t\t\t\tEXEC (@query)\r\n", "\t\t\t\tINSERT INTO #dbinfo\r\n", "\t\t\t\t\t(dbname, lst_known_checkdb)\r\n", "\t\t\t\tSELECT @dbname, [value]\r\n", "\t\t\t\tFROM #output_dbinfo\r\n", "\t\t\t\tWHERE Field LIKE \u0027dbi_dbccLastKnownGood%\u0027;\r\n", "\t\t\t\tUPDATE #dbinfo\r\n", "\t\t\tSET #dbinfo.updSysCatalog = #output_dbinfo.[value]\r\n", "\t\t\tFROM #output_dbinfo \r\n", "\t\t\tWHERE #dbinfo.dbname = @dbname AND #output_dbinfo.Field LIKE \u0027dbi_updSysCatalog%\u0027;\r\n", "\t\t\t\tUPDATE #dbinfo\r\n", "\t\t\tSET #dbinfo.dbi_createVersion = #output_dbinfo.[value]\r\n", "\t\t\tFROM #output_dbinfo \r\n", "\t\t\tWHERE #dbinfo.dbname = @dbname AND #output_dbinfo.Field LIKE \u0027dbi_createVersion%\u0027;\r\n", "\t\t\t\tUPDATE #dbinfo\r\n", "\t\t\tSET #dbinfo.dbi_dbccFlags = #output_dbinfo.[value]\r\n", "\t\t\tFROM #output_dbinfo \r\n", "\t\t\tWHERE #dbinfo.dbname = @dbname AND #output_dbinfo.Field LIKE \u0027dbi_dbccFlags%\u0027;\r\n", "\t\t\tEND;\r\n", "\t\t\tTRUNCATE TABLE #output_dbinfo;\r\n", "\t\t\tFETCH NEXT FROM curDBs INTO @dbname\r\n", "\t\tEND\r\n", "\t\tCLOSE curDBs\r\n", "\t\tDEALLOCATE curDBs;\r\n", "\t;\r\n", "\t\tWITH\r\n", "\t\t\tcte_dbcc (name, lst_known_checkdb)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT sd.name, tmpdbi.lst_known_checkdb\r\n", "\t\t\t\tFROM master.sys.databases sd (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON sd.name = tmpdbi.dbname\r\n", "\t\t\t\tWHERE sd.database_id <> 2 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\t)\r\n", "\t\tSELECT @dbcc = CASE WHEN COUNT(name) > 0 THEN 1 ELSE 0 END\r\n", "\t\tFROM cte_dbcc\r\n", "\t\tWHERE DATEDIFF(dd, lst_known_checkdb, GETDATE()) > 7 OR lst_known_checkdb IS NULL;\r\n", "\t\t;WITH\r\n", "\t\t\tcte_catupd (name, updSysCatalog)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT sd.name, tmpdbi.updSysCatalog\r\n", "\t\t\t\tFROM master.sys.databases sd (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON sd.name = tmpdbi.dbname\r\n", "\t\t\t\tWHERE sd.database_id <> 2 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\t)\r\n", "\t\tSELECT @catupd = CASE WHEN COUNT(name) > 0 THEN 1 ELSE 0 END\r\n", "\t\tFROM cte_catupd\r\n", "\t\tWHERE updSysCatalog > \u00271900-01-01 00:00:00.000\u0027;\r\n", "\t\t;WITH\r\n", "\t\t\tcte_purity (name, dbi_createVersion, dbi_dbccFlags)\r\n", "\t\t\tAS\r\n", "\t\t\t(\r\n", "\t\t\t\tSELECT sd.name, tmpdbi.dbi_createVersion, tmpdbi.dbi_dbccFlags\r\n", "\t\t\t\tFROM master.sys.databases sd (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON sd.name = tmpdbi.dbname\r\n", "\t\t\t\tWHERE sd.database_id > 4 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\t)\r\n", "\t\tSELECT @purity = CASE WHEN COUNT(name) > 0 THEN 1 ELSE 0 END\r\n", "\t\tFROM cte_purity\r\n", "\t\tWHERE dbi_createVersion <= 611 AND dbi_dbccFlags = 0;\r\n", "\t-- <= SQL Server 2005\r\n", "\t\tIF @dbcc = 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027DBCC_CHECKDB\u0027 AS [Check], \u0027[WARNING: database integrity checks have not been executed for over 7 days on some or all databases. It is recommended to run DBCC CHECKDB on these databases as soon as possible]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027DBCC_CHECKDB\u0027 AS [Information], [name] AS [Database_Name], MAX(lst_known_checkdb) AS Last_Known_CHECKDB\r\n", "\t\t\tFROM master.sys.databases (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON name = tmpdbi.dbname\r\n", "\t\t\tWHERE database_id <> 2 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\tGROUP BY [name]\r\n", "\t\t\tHAVING DATEDIFF(dd, MAX(lst_known_checkdb), GETDATE()) > 7 OR MAX(lst_known_checkdb) IS NULL\r\n", "\t\t\tORDER BY [name]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027DBCC_CHECKDB\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t\tIF @catupd = 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Direct_Catalog_Updates\u0027 AS [Check], \u0027[WARNING: Microsoft does not support direct catalog updates to databases.]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT DISTINCT \u0027Instance_checks\u0027 AS [Category], \u0027Direct_Catalog_Updates\u0027 AS [Information], [name] AS [Database_Name], MAX(updSysCatalog) AS Last_Direct_Catalog_Update\r\n", "\t\t\tFROM master.sys.databases (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON name = tmpdbi.dbname\r\n", "\t\t\tWHERE database_id <> 2 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\tGROUP BY [name]\r\n", "\t\t\tHAVING (MAX(updSysCatalog) > \u00271900-01-01 00:00:00.000\u0027)\r\n", "\t\t\tORDER BY [name]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Instance_checks\u0027 AS [Category], \u0027Direct_Catalog_Updates\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\t-- http://support.microsoft.com/kb/923247/en-us\r\n", "\t-- http://www.sqlskills.com/blogs/paul/checkdb-from-every-angle-how-to-tell-if-data-purity-checks-will-be-run\r\n", "\t\tIF @purity = 1\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Databases_need_data_purity_check\u0027 AS [Check], \u0027[WARNING: Databases were found that need to run data purity checks.]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT DISTINCT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Databases_need_data_purity_check\u0027 AS [Information], [name] AS [Database_Name], dbi_dbccFlags AS Needs_Data_Purity_Checks\r\n", "\t\t\tFROM master.sys.databases (NOLOCK) LEFT JOIN #dbinfo tmpdbi ON name = tmpdbi.dbname\r\n", "\t\t\tWHERE database_id > 4 AND dbi_createVersion <= 611 AND dbi_dbccFlags = 0 AND is_read_only = 0 AND [state] = 0\r\n", "\t\t\tORDER BY [name]\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Databases_need_data_purity_check\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Only a sysadmin can run the \"DBCC CHECKDB, Direct Catalog Updates and Data Purity\" checks. Bypassing check]\u0027, 16, 1, N\u0027sysadmin\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "505b94fa-e2c8-4121-98e9-1a49329bf538", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### AlwaysOn/Mirroring automatic page repair subsection\r\n", "Refer to \"Automatic Page Repair\" BOL entry for more information (https://docs.microsoft.com/sql/sql-server/failover-clusters/automatic-page-repair-availability-groups-database-mirroring)\r\n" ], "metadata": { "azdata_cell_guid": "e1050e2c-ba66-476a-b7ee-39f74924b5ed" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 9\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting AlwaysOn/Mirroring automatic page repair\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF @sqlmajorver > 10\r\n", "\tBEGIN\r\n", "\t\t\tDECLARE @HadrRep int--, @sqlcmd NVARCHAR(4000), @params NVARCHAR(500)\r\n", "\t\t\tSET @sqlcmd = N\u0027SELECT @HadrRepOUT = COUNT(*) FROM sys.dm_hadr_auto_page_repair\u0027;\r\n", "\t\t\tSET @params = N\u0027@HadrRepOUT int OUTPUT\u0027;\r\n", "\t\t\tEXECUTE sp_executesql @sqlcmd, @params, @HadrRepOUT=@HadrRep OUTPUT;\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSET @HadrRep = 0\r\n", "\t\tEND;\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#pagerepair\u0027))\r\n", "\tDROP TABLE #pagerepair;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#pagerepair\u0027))\r\n", "\tCREATE TABLE #pagerepair\r\n", "\t\t(\r\n", "\t\t\trowid int IDENTITY(1,1) PRIMARY KEY CLUSTERED,\r\n", "\t\t\tdbname NVARCHAR(255),\r\n", "\t\t\t[file_id] int NULL,\r\n", "\t\t\t[page_id] bigint NULL,\r\n", "\t\t\terror_type smallint NULL,\r\n", "\t\t\tpage_status tinyint NULL,\r\n", "\t\t\tlst_modification_time DATETIME NULL,\r\n", "\t\t\tRepair_Source VARCHAR(20) NULL\r\n", "\t\t)\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM sys.dm_db_mirroring_auto_page_repair (NOLOCK)) > 0\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #pagerepair\r\n", "\t\t\tSELECT DB_NAME(database_id) AS [Database_Name], [file_id], [page_id], [error_type], page_status, MAX(modification_time), \u0027Mirroring\u0027 AS [Repair_Source]\r\n", "\t\t\tFROM sys.dm_db_mirroring_auto_page_repair (NOLOCK)\r\n", "\t\t\tGROUP BY database_id, [file_id], [page_id], [error_type], page_status\r\n", "\t\tEND\r\n", "\t\tIF @HadrRep > 0\r\n", "\tBEGIN\r\n", "\t\t\tINSERT INTO #pagerepair\r\n", "\t\t\tEXEC (\u0027SELECT DB_NAME(database_id) AS [Database_Name], [file_id], [page_id], [error_type], page_status, MAX(modification_time), \u0027\u0027HADR\u0027\u0027 AS [Repair_Source] FROM sys.dm_hadr_auto_page_repair GROUP BY database_id, [file_id], [page_id], [error_type], page_status ORDER BY DB_NAME(database_id), MAX(modification_time) DESC, [file_id], [page_id]\u0027)\r\n", "\t\tEND;\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\t\tFROM sys.dm_db_mirroring_auto_page_repair (NOLOCK)) > 0\r\n", "\t\t\tOR @HadrRep > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Auto_Page_repairs\u0027 AS [Check], \u0027[WARNING: Page repairs have been found. Check for suspect pages]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Auto_Page_repairs\u0027 AS [Information], dbname AS [Database_Name],\r\n", "\t\t\t\t[file_id] AS [File_ID],\r\n", "\t\t\t\t[page_id] AS [Page_ID],\r\n", "\t\t\t\tCASE [error_type]\r\n", "\t\t\t\tWHEN -1 THEN \u0027Error 823\u0027\r\n", "\t\t\t\tWHEN 1 THEN \u0027Unspecified Error 824\u0027\r\n", "\t\t\t\tWHEN 2 THEN \u0027Bad Checksum\u0027\r\n", "\t\t\t\tWHEN 3 THEN \u0027Torn Page\u0027\r\n", "\t\t\t\tELSE NULL\r\n", "\t\t\tEND AS [Error_Type],\r\n", "\t\t\t\tCASE page_status \r\n", "\t\t\t\tWHEN 2 THEN \u0027Queued for request from partner\u0027\r\n", "\t\t\t\tWHEN 3 THEN \u0027Request sent to partner\u0027\r\n", "\t\t\t\tWHEN 4 THEN \u0027Queued for automatic page repair\u0027 \r\n", "\t\t\t\tWHEN 5 THEN \u0027Automatic page repair succeeded\u0027\r\n", "\t\t\t\tWHEN 6 THEN \u0027Irreparable\u0027\r\n", "\t\t\tEND AS [Page_Status],\r\n", "\t\t\t\tlst_modification_time AS [Last_Modification_Time], [Repair_Source]\r\n", "\t\t\tFROM #pagerepair\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Auto_Page_repairs\u0027 AS [Check], \u0027[None]\u0027 AS [Deviation], \u0027\u0027 AS [Source]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "477e39ee-853b-4317-b9b0-8ec9ed1cb0d8", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Suspect pages subsection\r\n", "Refer to \"Manage the suspect_pages Table\" BOL entry for more information (https://docs.microsoft.com/sql/relational-databases/backup-restore/manage-the-suspect-pages-table-sql-server)\r\n" ], "metadata": { "azdata_cell_guid": "123d6cf6-47c0-44f7-b011-aed3bd105d63" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Suspect pages\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF (SELECT COUNT(*)\r\n", "\tFROM msdb.dbo.suspect_pages\r\n", "\tWHERE (event_type = 1 OR event_type = 2 OR event_type = 3)) > 0\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Suspect_Pages\u0027 AS [Check], \u0027[WARNING: Suspect pages have been found. Run DBCC CHECKDB to verify affected databases]\u0027 AS [Deviation]\r\n", "\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Suspect_Pages\u0027 AS [Information], DB_NAME(database_id) AS [Database_Name],\r\n", "\t\t\t[file_id] AS [File_ID],\r\n", "\t\t\t[page_id] AS [Page_ID],\r\n", "\t\t\tCASE event_type\r\n", "\t\t\tWHEN 1 THEN \u0027Error 823 or unspecified Error 824\u0027\r\n", "\t\t\tWHEN 2 THEN \u0027Bad Checksum\u0027\r\n", "\t\t\tWHEN 3 THEN \u0027Torn Page\u0027\r\n", "\t\t\tELSE NULL\r\n", "\t\tEND AS [Event_Type],\r\n", "\t\t\terror_count AS [Error_Count],\r\n", "\t\t\tlast_update_date AS [Last_Update_Date]\r\n", "\t\tFROM msdb.dbo.suspect_pages (NOLOCK)\r\n", "\t\tWHERE (event_type = 1 OR event_type = 2 OR event_type = 3)\r\n", "\t\tORDER BY DB_NAME(database_id), last_update_date DESC, [file_id], [page_id]\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Suspect_Pages\u0027 AS [Check], \u0027[None]\u0027 AS [Deviation]\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "2de2c4e7-5252-4c6a-b7f9-f56669efeb47", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Replication Errors subsection\r\n" ], "metadata": { "azdata_cell_guid": "b200850a-7c57-4f02-9c6f-f8b252563efe" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @replication = 1 AND (SELECT COUNT(*)\r\n", "\t\tFROM master.sys.databases (NOLOCK)\r\n", "\t\tWHERE [name] = \u0027distribution\u0027) > 0\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting Replication Errors\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM distribution.dbo.MSdistribution_history AS msh\r\n", "\t\t\tINNER JOIN distribution.dbo.MSrepl_errors AS mse ON mse.id = msh.error_id\r\n", "\t\t\tINNER JOIN distribution.dbo.MSdistribution_agents AS msa ON msh.agent_id = msa.id\r\n", "\t\tWHERE mse.time >= DATEADD(hh, - 24, GETDATE())) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Repl_Errors_Lst_24H\u0027 AS [Check], \u0027[WARNING: Replication Errors have been found in the last 24 hours]\u0027 AS [Deviation]\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Repl_Errors_Lst_24H\u0027 AS [Information],\r\n", "\t\t\t\tmsa.[name] AS [Distribution_Agent], msa.publisher_db AS [Publisher_DB],\r\n", "\t\t\t\tmsa.publication AS [Publication], msa.subscriber_db AS [Subscriber_DB], mse.error_code\r\n", "\t\t\tFROM distribution.dbo.MSdistribution_history AS msh\r\n", "\t\t\t\tINNER JOIN distribution.dbo.MSrepl_errors AS mse ON mse.id = msh.error_id\r\n", "\t\t\t\tINNER JOIN distribution.dbo.MSdistribution_agents AS msa ON msh.agent_id = msa.id\r\n", "\t\t\tWHERE mse.time >= DATEADD(hh, - 24, GETDATE())\r\n", "\t\t\tGROUP BY msa.[name], msa.publisher_db, msa.publication, msa.subscriber_db, mse.error_code\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Repl_Errors_Details\u0027 AS [Information], msh.time,\r\n", "\t\t\t\tmsa.[name] AS [Distribution_Agent], msa.publisher_db AS [Publisher_DB],\r\n", "\t\t\t\tmsa.publication AS [Publication], msa.subscriber_db AS [Subscriber_DB],\r\n", "\t\t\t\tmse.error_code, mse.error_text\r\n", "\t\t\tFROM distribution.dbo.MSdistribution_history AS msh (NOLOCK)\r\n", "\t\t\t\tINNER JOIN distribution.dbo.MSrepl_errors AS mse (NOLOCK) ON mse.id = msh.error_id AND mse.time = msh.time\r\n", "\t\t\t\tINNER JOIN distribution.dbo.MSdistribution_agents AS msa (NOLOCK) ON msh.agent_id = msa.id\r\n", "\t\t\tWHERE (mse.time >= DATEADD(hh, - 24, GETDATE()))\r\n", "\t\t\tORDER BY msh.time\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Repl_Errors_Lst_24H\u0027 AS [Check], \u0027[None]\u0027 AS [Deviation]\r\n", "\t\tEND\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "6514f448-e23f-4bbf-b8ff-a0d3c08fa3a4", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Errorlog based checks subsection\r\n", "- Because it is a string based search, add other search conditions as deemed fit. \r\n", "- You can set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n" ], "metadata": { "azdata_cell_guid": "2623d29b-c668-4985-bb52-230a231e6f40" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027 |-Starting Errorlog based checks\u0027, 10, 1) WITH NOWAIT\r\n", "--DECLARE @lognumber int, @logcount int\r\n", "\tIF ISNULL(IS_SRVROLEMEMBER(N\u0027sysadmin\u0027), 0) = 1 -- Is sysadmin\r\n", "\t\tOR ISNULL(IS_SRVROLEMEMBER(N\u0027securityadmin\u0027), 0) = 1 -- Is securityadmin\r\n", "\t\tOR ((SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027sp_readerrorlog\u0027) > 0\r\n", "\t\tAND (SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_readerrorlog\u0027) > 0\r\n", "\t\tAND (SELECT COUNT([name])\r\n", "\t\tFROM tempdb.dbo.permstbl\r\n", "\t\tWHERE [name] = \u0027xp_enumerrorlogs\u0027) > 0)\r\n", "BEGIN\r\n", "\t\tSET @lognumber = 0\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbcc\u0027))\r\n", "\tDROP TABLE #dbcc;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbcc\u0027))\r\n", "\tCREATE TABLE #dbcc\r\n", "\t\t(\r\n", "\t\t\trowid int IDENTITY(1,1) PRIMARY KEY,\r\n", "\t\t\tlogid int NULL,\r\n", "\t\t\tlogdate DATETIME,\r\n", "\t\t\tspid VARCHAR(50),\r\n", "\t\t\tlogmsg VARCHAR(4000)\r\n", "\t\t)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbcc\u0027))\r\n", "\tCREATE INDEX [dbcc_logmsg] ON dbo.[#dbcc](logid)\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#avail_logs\u0027))\r\n", "\tDROP TABLE #avail_logs;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#avail_logs\u0027))\r\n", "\tCREATE TABLE #avail_logs\r\n", "\t\t(\r\n", "\t\t\tlognum int,\r\n", "\t\t\tlogdate DATETIME,\r\n", "\t\t\tlogsize int\r\n", "\t\t)\r\n", "\t-- Get the number of available logs \r\n", "\t\tINSERT INTO #avail_logs\r\n", "\t\tEXEC xp_enumerrorlogs\r\n", "\t\tSELECT @logcount = MAX(lognum)\r\n", "\t\tFROM #avail_logs\r\n", "\t\tWHILE @lognumber < @logcount \r\n", "\tBEGIN\r\n", "\t\t-- Cycle thru sql error logs\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u002715 seconds\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 1. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027deadlock\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 2. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027stack dump\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 3. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027Error:\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 4. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027A significant part of sql server process memory has been paged out\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 5. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t\tSELECT @sqlcmd = \u0027EXEC master..sp_readerrorlog \u0027 + CONVERT(VARCHAR(3),@lognumber) + \u0027, 1, \u0027\u0027cachestore flush\u0027\u0027\u0027\r\n", "\t\t\tBEGIN TRY\r\n", "\t\t\tINSERT INTO #dbcc\r\n", "\t\t\t\t(logdate, spid, logmsg)\r\n", "\t\t\tEXECUTE (@sqlcmd);\r\n", "\t\t\tUPDATE #dbcc SET logid = @lognumber WHERE logid IS NULL;\r\n", "\t\tEND TRY\r\n", "\t\tBEGIN CATCH\r\n", "\t\t\tSELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;\r\n", "\t\t\tSELECT @ErrorMessage = \u0027Errorlog based subsection - Error raised in TRY block 6. \u0027 + ERROR_MESSAGE()\r\n", "\t\t\tRAISERROR (@ErrorMessage, 16, 1);\r\n", "\t\tEND CATCH\r\n", "\t\t-- Next log \r\n", "\t\t--SET @lognumber = @lognumber + 1 \r\n", "\t\t\tSELECT @lognumber = MIN(lognum)\r\n", "\t\t\tFROM #avail_logs\r\n", "\t\t\tWHERE lognum > @lognumber\r\n", "\t\tEND\r\n", "\t\tIF (SELECT COUNT([rowid])\r\n", "\t\tFROM #dbcc) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Errorlog\u0027 AS [Check], \u0027[WARNING: Errorlog contains important messages.]\u0027 AS [Deviation];\r\n", "\t\t\t;WITH\r\n", "\t\t\t\tcte_dbcc (err, errcnt, logdate, logmsg)\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT CASE WHEN logmsg LIKE \u0027Error: [^a-z]%\u0027 THEN RIGHT(LEFT(#dbcc.logmsg, CHARINDEX(\u0027,\u0027, #dbcc.logmsg)-1), CHARINDEX(\u0027,\u0027, #dbcc.logmsg)-8) \r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027SQL Server has encountered % longer than 15 seconds %\u0027 THEN CONVERT(CHAR(3),833)\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027A significant part of sql server process memory has been paged out%\u0027 THEN CONVERT(CHAR(5),17890)\r\n", "\t\t\t\t\tELSE NULL END AS err,\r\n", "\t\t\t\t\t\tCOUNT(logmsg) AS errcnt,\r\n", "\t\t\t\t\t\tlogdate,\r\n", "\t\t\t\t\t\tCASE WHEN logmsg LIKE \u0027SQL Server has encountered % longer than 15 seconds %\u0027 THEN \u0027SQL Server has encountered XXX occurrence(s) of IO requests taking longer than 15 seconds to complete on file YYY\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027A significant part of sql server process memory has been paged out%\u0027 THEN \u0027A significant part of sql server process memory has been paged out.\u0027\r\n", "\t\t\t\t\tELSE logmsg END AS logmsg\r\n", "\t\t\t\t\tFROM #dbcc\r\n", "\t\t\t\t\tGROUP BY logmsg, logdate\r\n", "\t\t\t\t)\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Errorlog_Summary\u0027 AS [Information],\r\n", "\t\t\t\terr AS [Error_Number],\r\n", "\t\t\t\tSUM(errcnt) AS Error_Count,\r\n", "\t\t\t\tMIN(logdate) AS [First_Logged_Date],\r\n", "\t\t\t\tMAX(logdate) AS [Last_Logged_Date],\r\n", "\t\t\t\tlogmsg AS [Logged_Message],\r\n", "\t\t\t\tCASE WHEN logmsg LIKE \u0027Error: 825%\u0027 THEN \u0027IO transient failure. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 833%\u0027 OR logmsg LIKE \u0027SQL Server has encountered % longer than 15 seconds %\u0027 THEN \u0027Long IO detected: http://support.microsoft.com/kb/897284\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 855%\u0027 OR logmsg LIKE \u0027Error: 856%\u0027 THEN \u0027Hardware memory corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 3452%\u0027 THEN \u0027Metadata inconsistency in DB. Run DBCC CHECKIDENT\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 3619%\u0027 THEN \u0027Chkpoint failed. No Log space available\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 9002%\u0027 THEN \u0027No Log space available\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17204%\u0027 OR logmsg LIKE \u0027Error: 17207%\u0027 THEN \u0027Error opening file during startup process\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17179%\u0027 THEN \u0027No AWE - LPIM related\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17890%\u0027 THEN \u0027sqlservr process paged out\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 2508%\u0027 THEN \u0027Catalog views inaccuracies in DB. Run DBCC UPDATEUSAGE\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 2511%\u0027 THEN \u0027Index Keys errors\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 3271%\u0027 THEN \u0027IO nonrecoverable error\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5228%\u0027 OR logmsg LIKE \u0027Error: 5229%\u0027 THEN \u0027Online Index operation errors\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5242%\u0027 THEN \u0027Page structural inconsistency\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5243%\u0027 THEN \u0027In-memory structural inconsistency\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5250%\u0027 THEN \u0027Corrupt page. Error cannot be fixed\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5901%\u0027 THEN \u0027Chkpoint failed. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17130%\u0027 THEN \u0027No lock memory\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17300%\u0027 THEN \u0027Unable to run new system task\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 802%\u0027 THEN \u0027No BP memory\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 845%\u0027 OR logmsg LIKE \u0027Error: 1105%\u0027 OR logmsg LIKE \u0027Error: 1121%\u0027 THEN \u0027No disk space available\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 1214%\u0027 THEN \u0027Internal parallelism error\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 823%\u0027 OR logmsg LIKE \u0027Error: 824%\u0027 THEN \u0027IO failure. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 832%\u0027 THEN \u0027Page checksum error. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 3624%\u0027 OR logmsg LIKE \u0027Error: 17065%\u0027 OR logmsg LIKE \u0027Error: 17066%\u0027 OR logmsg LIKE \u0027Error: 17067%\u0027 THEN \u0027System assertion check failed. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5572%\u0027 THEN \u0027Possible FILESTREAM corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 9100%\u0027 THEN \u0027Possible index corruption\u0027\r\n", "\t\t\t-- How To Diagnose and Correct Errors 17883, 17884, 17887, and 17888 (http://technet.microsoft.com/library/cc917684.aspx)\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17883%\u0027 THEN \u0027Non-yielding scheduler: http://technet.microsoft.com/library/cc917684.aspx\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17884%\u0027 OR logmsg LIKE \u0027Error: 17888%\u0027 THEN \u0027Deadlocked scheduler: http://technet.microsoft.com/library/cc917684.aspx\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 17887%\u0027 THEN \u0027IO completion error: http://technet.microsoft.com/library/cc917684.aspx\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 1205%\u0027 THEN \u0027Deadlocked transaction\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 610%\u0027 THEN \u0027Page header invalid. Possible corruption\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 8621%\u0027 THEN \u0027QP stack overflow during optimization. Please simplify the query\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 8642%\u0027 THEN \u0027QP insufficient threads for parallelism\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 701%\u0027 THEN \u0027Insufficient memory\u0027\r\n", "\t\t\t-- How to troubleshoot SQL Server error 8645 (http://support.microsoft.com/kb/309256)\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 8645%\u0027 THEN \u0027Insufficient memory: http://support.microsoft.com/kb/309256\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 605%\u0027 THEN \u0027Page retrieval failed. Possible corruption\u0027\r\n", "\t\t\t-- How to troubleshoot Msg 5180 (http://support.microsoft.com/kb/2015747)\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 5180%\u0027 THEN \u0027Invalid file ID. Possible corruption: http://support.microsoft.com/kb/2015747\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 8966%\u0027 THEN \u0027Unable to read and latch on a PFS or GAM page\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 9001%\u0027 OR logmsg LIKE \u0027Error: 9002%\u0027 THEN \u0027Transaction log errors.\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027Error: 9003%\u0027 OR logmsg LIKE \u0027Error: 9004%\u0027 OR logmsg LIKE \u0027Error: 9015%\u0027 THEN \u0027Transaction log errors. Possible corruption\u0027\r\n", "\t\t\t-- How to reduce paging of buffer pool memory in the 64-bit version of SQL Server (http://support.microsoft.com/kb/918483)\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027A significant part of sql server process memory has been paged out%\u0027 THEN \u0027SQL Server process was trimmed by the OS. Preventable if LPIM is granted\u0027\r\n", "\t\t\t\tWHEN logmsg LIKE \u0027%cachestore flush%\u0027 THEN \u0027CacheStore flush\u0027\r\n", "\t\t\tELSE \u0027\u0027 END AS [Comment],\r\n", "\t\t\t\tCASE WHEN logmsg LIKE \u0027Error: [^a-z]%\u0027 THEN (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(text,\u0027%.*ls\u0027,\u0027%\u0027),\u0027%d\u0027,\u0027%\u0027),\u0027%ls\u0027,\u0027%\u0027),\u0027%S_MSG\u0027,\u0027%\u0027),\u0027%S_PGID\u0027,\u0027%\u0027),\u0027%#016I64x\u0027,\u0027%\u0027),\u0027%p\u0027,\u0027%\u0027),\u0027%08x\u0027,\u0027%\u0027),\u0027%u\u0027,\u0027%\u0027),\u0027%I64d\u0027,\u0027%\u0027),\u0027%s\u0027,\u0027%\u0027),\u0027%ld\u0027,\u0027%\u0027),\u0027%lx\u0027,\u0027%\u0027), \u0027%%%\u0027, \u0027%\u0027)\r\n", "\t\t\t\tFROM sys.messages\r\n", "\t\t\t\tWHERE message_id = (CONVERT(int, RIGHT(LEFT(cte_dbcc.logmsg, CHARINDEX(\u0027,\u0027, cte_dbcc.logmsg)-1), CHARINDEX(\u0027,\u0027, cte_dbcc.logmsg)-8))) AND language_id = @langid) \r\n", "\t\t\t\tELSE \u0027\u0027 END AS [Look_for_Message_example]\r\n", "\t\t\tFROM cte_dbcc\r\n", "\t\t\tGROUP BY err, logmsg\r\n", "\t\t\tORDER BY SUM(errcnt) DESC;\r\n", "\t\t\tIF @logdetail = 1\r\n", "\t\tBEGIN\r\n", "\t\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Errorlog_Detail\u0027 AS [Information], logid AS [Errorlog_Id], logdate AS [Logged_Date], spid AS [Process], logmsg AS [Logged_Message],\r\n", "\t\t\t\t\tCASE WHEN logmsg LIKE \u0027Error: 825%\u0027 THEN \u0027IO transient failure. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 833%\u0027 OR logmsg LIKE \u0027SQL Server has encountered % longer than 15 seconds %\u0027 THEN \u0027Long IO detected\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 855%\u0027 OR logmsg LIKE \u0027Error: 856%\u0027 THEN \u0027Hardware memory corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 3452%\u0027 THEN \u0027Metadata inconsistency in DB. Run DBCC CHECKIDENT\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 3619%\u0027 THEN \u0027Chkpoint failed. No Log space available\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 9002%\u0027 THEN \u0027No Log space available\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17179%\u0027 THEN \u0027No AWE - LPIM related\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17890%\u0027 THEN \u0027sqlservr process paged out\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17204%\u0027 OR logmsg LIKE \u0027Error: 17207%\u0027 THEN \u0027Error opening file during startup process\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 2508%\u0027 THEN \u0027Catalog views inaccuracies in DB. Run DBCC UPDATEUSAGE\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 2511%\u0027 THEN \u0027Index Keys errors\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 3271%\u0027 THEN \u0027IO nonrecoverable error\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5228%\u0027 OR logmsg LIKE \u0027Error: 5229%\u0027 THEN \u0027Online Index operation errors\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5242%\u0027 THEN \u0027Page structural inconsistency\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5243%\u0027 THEN \u0027In-memory structural inconsistency\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5250%\u0027 THEN \u0027Corrupt page. Error cannot be fixed\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5901%\u0027 THEN \u0027Chkpoint failed. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17130%\u0027 THEN \u0027No lock memory\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17300%\u0027 THEN \u0027Unable to run new system task\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 802%\u0027 THEN \u0027No BP memory\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 845%\u0027 OR logmsg LIKE \u0027Error: 1105%\u0027 OR logmsg LIKE \u0027Error: 1121%\u0027 THEN \u0027No disk space available\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 1214%\u0027 THEN \u0027Internal parallelism error\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 823%\u0027 OR logmsg LIKE \u0027Error: 824%\u0027 THEN \u0027IO failure. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 832%\u0027 THEN \u0027Page checksum error. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 3624%\u0027 OR logmsg LIKE \u0027Error: 17065%\u0027 OR logmsg LIKE \u0027Error: 17066%\u0027 OR logmsg LIKE \u0027Error: 17067%\u0027 THEN \u0027System assertion check failed. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5572%\u0027 THEN \u0027Possible FILESTREAM corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 9100%\u0027 THEN \u0027Possible index corruption\u0027\r\n", "\t\t\t\t-- How To Diagnose and Correct Errors 17883, 17884, 17887, and 17888 (http://technet.microsoft.com/library/cc917684.aspx)\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17883%\u0027 THEN \u0027Non-yielding scheduler\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17884%\u0027 OR logmsg LIKE \u0027Error: 17888%\u0027 THEN \u0027Deadlocked scheduler\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 17887%\u0027 THEN \u0027IO completion error\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 1205%\u0027 THEN \u0027Deadlocked transaction\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 610%\u0027 THEN \u0027Page header invalid. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 8621%\u0027 THEN \u0027QP stack overflow during optimization. Please simplify the query\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 8642%\u0027 THEN \u0027QP insufficient threads for parallelism\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 701%\u0027 THEN \u0027Insufficient memory\u0027\r\n", "\t\t\t\t-- How to troubleshoot SQL Server error 8645 (http://support.microsoft.com/kb/309256)\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 8645%\u0027 THEN \u0027Insufficient memory\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 605%\u0027 THEN \u0027Page retrieval failed. Possible corruption\u0027\r\n", "\t\t\t\t-- How to troubleshoot Msg 5180 (http://support.microsoft.com/kb/2015747)\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 5180%\u0027 THEN \u0027Invalid file ID. Possible corruption\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 8966%\u0027 THEN \u0027Unable to read and latch on a PFS or GAM page\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 9001%\u0027 OR logmsg LIKE \u0027Error: 9002%\u0027 THEN \u0027Transaction log errors.\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027Error: 9003%\u0027 OR logmsg LIKE \u0027Error: 9004%\u0027 OR logmsg LIKE \u0027Error: 9015%\u0027 THEN \u0027Transaction log errors. Possible corruption\u0027\r\n", "\t\t\t\t-- How to reduce paging of buffer pool memory in the 64-bit version of SQL Server (http://support.microsoft.com/kb/918483)\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027A significant part of sql server process memory has been paged out%\u0027 THEN \u0027SQL Server process was trimmed by the OS. Preventable if LPIM is granted\u0027\r\n", "\t\t\t\t\tWHEN logmsg LIKE \u0027%cachestore flush%\u0027 THEN \u0027CacheStore flush\u0027\r\n", "\t\t\t\tELSE \u0027\u0027 END AS [Comment]\r\n", "\t\t\t\tFROM #dbcc\r\n", "\t\t\t\tORDER BY logdate DESC\r\n", "\t\t\tEND\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027Errorlog\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND\r\n", "ELSE\r\n", "BEGIN\r\n", "\t\tRAISERROR(\u0027[WARNING: Only a sysadmin or securityadmin can run the \"Errorlog\" check. Bypassing check]\u0027, 16, 1, N\u0027permissions\u0027)\r\n", "\t\tRAISERROR(\u0027[WARNING: If not sysadmin or securityadmin, then user must be a granted EXECUTE permissions on the following sprocs to run checks: xp_enumerrorlogs and sp_readerrorlog. Bypassing check]\u0027, 16, 1, N\u0027extended_sprocs\u0027)\r\n", "--RETURN\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "350c6f15-0930-4210-ab8e-1b15d4e939c9", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### System health error checks subsection\r\n" ], "metadata": { "azdata_cell_guid": "decf6107-cb02-4fdd-aa28-93deaebf90ea" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "\t\tRAISERROR (N\u0027 |-Starting System health checks\u0027, 10, 1) WITH NOWAIT\r\n", "\t\tIF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#SystemHealthSessionData\u0027))\r\n", "\tDROP TABLE #SystemHealthSessionData;\r\n", "\t\tIF NOT EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#SystemHealthSessionData\u0027))\r\n", "\tCREATE TABLE #SystemHealthSessionData\r\n", "\t\t(\r\n", "\t\t\ttarget_data XML\r\n", "\t\t)\r\n", "\t-- Store the XML data in a temporary table\r\n", "\t\tINSERT INTO #SystemHealthSessionData\r\n", "\t\tSELECT CAST(xet.target_data AS XML)\r\n", "\t\tFROM sys.dm_xe_session_targets xet\r\n", "\t\t\tINNER JOIN sys.dm_xe_sessions xe ON xe.address = xet.event_session_address\r\n", "\t\tWHERE xe.name = \u0027system_health\u0027\r\n", "\t\tIF (SELECT COUNT(*)\r\n", "\t\tFROM #SystemHealthSessionData a\r\n", "\t\tWHERE CONVERT(VARCHAR(max), target_data) LIKE \u0027%error_reported%\u0027) > 0\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027SystemHealth_Errors\u0027 AS [Check], \u0027[WARNING: System Health Session contains important messages.]\u0027 AS [Deviation];\r\n", "\t\t-- Get statistical information about all the errors reported\r\n", "\t\t\t;WITH\r\n", "\t\t\t\tcteHealthSession (EventXML)\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT C.query(\u0027.\u0027) EventXML\r\n", "\t\t\t\t\tFROM #SystemHealthSessionData a\r\n", "\t\t\tCROSS APPLY a.target_data.nodes(\u0027/RingBufferTarget/event\u0027) AS T(C)\r\n", "\t\t\t\t),\r\n", "\t\t\t\tcteErrorReported (EventTime, ErrorNumber)\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT EventXML.value(\u0027(/event/@timestamp)[1]\u0027, \u0027datetime\u0027) AS EventTime,\r\n", "\t\t\t\t\t\tEventXML.value(\u0027(/event/data[@name=\"error_number\"]/value)[1]\u0027, \u0027int\u0027) AS ErrorNumber\r\n", "\t\t\t\t\tFROM cteHealthSession\r\n", "\t\t\t\t\tWHERE EventXML.value(\u0027(/event/@name)[1]\u0027, \u0027VARCHAR(500)\u0027) = \u0027error_reported\u0027\r\n", "\t\t\t\t)\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027SystemHealth_Errors_Summary\u0027 AS [Information],\r\n", "\t\t\t\tErrorNumber AS [Error_Number],\r\n", "\t\t\t\tMIN(EventTime) AS [First_Logged_Date],\r\n", "\t\t\t\tMAX(EventTime) AS [Last_Logged_Date],\r\n", "\t\t\t\tCOUNT(ErrorNumber) AS Error_Count,\r\n", "\t\t\t\tREPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(b.text,\u0027%.*ls\u0027,\u0027%\u0027),\u0027%d\u0027,\u0027%\u0027),\u0027%ls\u0027,\u0027%\u0027),\u0027%S_MSG\u0027,\u0027%\u0027),\u0027%S_PGID\u0027,\u0027%\u0027),\u0027%#016I64x\u0027,\u0027%\u0027),\u0027%p\u0027,\u0027%\u0027),\u0027%08x\u0027,\u0027%\u0027),\u0027%u\u0027,\u0027%\u0027),\u0027%I64d\u0027,\u0027%\u0027),\u0027%s\u0027,\u0027%\u0027),\u0027%ld\u0027,\u0027%\u0027),\u0027%lx\u0027,\u0027%\u0027), \u0027%%%\u0027, \u0027%\u0027) AS [Look_for_Message_example]\r\n", "\t\t\tFROM cteErrorReported a\r\n", "\t\t\t\tINNER JOIN sys.messages b ON a.ErrorNumber = b.message_id\r\n", "\t\t\tWHERE b.language_id = @langid\r\n", "\t\t\tGROUP BY a.ErrorNumber, b.[text]\r\n", "\t\t-- Get detailed information about all the errors reported\r\n", "\t\t\t;WITH\r\n", "\t\t\t\tcteHealthSession\r\n", "\t\t\t\tAS\r\n", "\t\t\t\t(\r\n", "\t\t\t\t\tSELECT C.query(\u0027.\u0027).value(\u0027(/event/@timestamp)[1]\u0027, \u0027datetime\u0027) AS EventTime,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/data[@name=\"error_number\"]/value)[1]\u0027, \u0027int\u0027) AS ErrorNumber,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/data[@name=\"severity\"]/value)[1]\u0027, \u0027int\u0027) AS ErrorSeverity,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/data[@name=\"state\"]/value)[1]\u0027, \u0027int\u0027) AS ErrorState,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/data[@name=\"message\"]/value)[1]\u0027, \u0027VARCHAR(MAX)\u0027) AS ErrorText,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/action[@name=\"session_id\"]/value)[1]\u0027, \u0027int\u0027) AS SessionID,\r\n", "\t\t\t\t\t\tC.query(\u0027.\u0027).value(\u0027(/event/data[@name=\"category\"]/text)[1]\u0027, \u0027VARCHAR(10)\u0027) AS ErrorCategory\r\n", "\t\t\t\t\tFROM #SystemHealthSessionData a\r\n", "\t\t\tCROSS APPLY a.target_data.nodes(\u0027/RingBufferTarget/event\u0027) AS T(C)\r\n", "\t\t\t\t\tWHERE C.query(\u0027.\u0027).value(\u0027(/event/@name)[1]\u0027, \u0027VARCHAR(500)\u0027) = \u0027error_reported\u0027\r\n", "\t\t\t\t)\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027SystemHealth_Errors_Detail\u0027 AS [Information],\r\n", "\t\t\t\tEventTime AS [Logged_Date],\r\n", "\t\t\t\tErrorNumber AS [Error_Number],\r\n", "\t\t\t\tErrorSeverity AS [Error_Sev],\r\n", "\t\t\t\tErrorState AS [Error_State],\r\n", "\t\t\t\tErrorText AS [Logged_Message],\r\n", "\t\t\t\tSessionID\r\n", "\t\t\tFROM cteHealthSession\r\n", "\t\t\tORDER BY EventTime\r\n", "\t\tEND\r\n", "\tELSE\r\n", "\tBEGIN\r\n", "\t\t\tSELECT \u0027Maintenance_Monitoring_checks\u0027 AS [Category], \u0027SystemHealth_Errors\u0027 AS [Check], \u0027[OK]\u0027 AS [Deviation]\r\n", "\t\tEND;\r\n", "\tEND;\r\n" ], "metadata": { "azdata_cell_guid": "3ed55588-c5d1-4a76-81f4-1ab8a2e44656", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 }, { "cell_type": "markdown", "source": [ "---\r\n", "---\r\n", "### Clean up temp objects\r\n" ], "metadata": { "azdata_cell_guid": "0ca50137-7be1-4950-9605-e602455e9cea" } }, { "cell_type": "code", "source": [ "-- These are the variables that are required for the Azure Data Studio Notebook to function in the same way as the stored procedure. Unfortunately, it is easier to add them to the beginning of each code block. \r\n", "SET NOCOUNT ON;\r\n", "SET ANSI_WARNINGS ON;\r\n", "SET QUOTED_IDENTIFIER ON;\r\n", "-- Declare Global Variables\r\n", "DECLARE @UpTime VARCHAR(12),@StartDate DATETIME\r\n", "DECLARE @agt smallint, @ole smallint, @sao smallint, @xcmd smallint\r\n", "DECLARE @ErrorSeverity int, @ErrorState int, @ErrorMessage NVARCHAR(4000)\r\n", "DECLARE @CMD NVARCHAR(4000)\r\n", "DECLARE @path NVARCHAR(2048)\r\n", "DECLARE @osver VARCHAR(5), @ostype VARCHAR(10), @osdistro VARCHAR(20), @server VARCHAR(128), @instancename NVARCHAR(128), @arch smallint, @ossp VARCHAR(25), @SystemManufacturer VARCHAR(128), @BIOSVendor AS VARCHAR(128), @Processor_Name AS VARCHAR(128)\r\n", "DECLARE @existout int, @FSO int, @FS int, @OLEResult int, @FileID int\r\n", "DECLARE @FileName VARCHAR(200), @Text1 VARCHAR(2000), @CMD2 VARCHAR(100)\r\n", "DECLARE @src VARCHAR(255), @desc VARCHAR(255), @psavail VARCHAR(20), @psver tinyint\r\n", "DECLARE @dbid int, @dbname NVARCHAR(1000)\r\n", "DECLARE @sqlcmd NVARCHAR(max), @params NVARCHAR(600)\r\n", "DECLARE @sqlmajorver int, @sqlminorver int, @sqlbuild int, @masterpid int, @clustered bit\r\n", "DECLARE @ptochecks int\r\n", "DECLARE @dbScope VARCHAR(256) \r\n", "DECLARE @port VARCHAR(15), @replication int, @RegKey NVARCHAR(255), @cpuaffin VARCHAR(300), @cpucount int, @numa int\r\n", "DECLARE @i int, @cpuaffin_fixed VARCHAR(300), @affinitymask NVARCHAR(64), @affinity64mask NVARCHAR(1024)--, @cpuover32 int\r\n", "DECLARE @bpool_consumer bit\r\n", "DECLARE @allow_xpcmdshell bit\r\n", "DECLARE @custompath NVARCHAR(500) = NULL\r\n", "DECLARE @affined_cpus int\r\n", "DECLARE @langid smallint\r\n", "DECLARE @lpim bit, @lognumber int, @logcount int\r\n", "DECLARE @query NVARCHAR(1000)\r\n", "DECLARE @diskfrag bit\r\n", "DECLARE @accntsqlservice NVARCHAR(128)\r\n", "DECLARE @maxservermem bigint, @systemmem bigint\r\n", "DECLARE @mwthreads_count int\r\n", "DECLARE @ifi bit\r\n", "DECLARE @duration tinyint\r\n", "DECLARE @adhoc smallint\r\n", "DECLARE @gen_scripts bit \r\n", "DECLARE @ixfrag bit\r\n", "DECLARE @ixfragscanmode VARCHAR(8) \r\n", "DECLARE @logdetail bit \r\n", "DECLARE @spn_check bit \r\n", "DECLARE @dbcmptlevel int\r\n", "-- With the variables declared we then set them. You can alter these values for different checks. The instructions will show where you should do this.\r\n", "-- Set @dbScope to the appropriate list of database IDs if there\u0027s a need to have a specific scope for database specific checks.\r\n", "-- Valid input should be numeric value(s) between single quotes, as follows: \u00271,6,15,123\u0027\r\n", "-- Leave NULL for all databases\r\n", "SELECT @dbScope = NULL -- (NULL = All DBs; \u0027\u0027)\r\n", "-- Set @ptochecks to OFF if you want to skip more performance tuning and optimization oriented checks.\r\n", "SELECT @ptochecks = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @duration to the number of seconds between data collection points regarding perf counters, waits and latches. -- Duration must be between 10s and 255s (4m 15s), with a default of 90s.\r\n", "SELECT @duration = 90\r\n", "-- Set @logdetail to OFF if you want to get just the summary info on issues in the Errorlog, rather than the full detail.\r\n", "SELECT @logdetail = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @diskfrag to ON if you want to check for disk physical fragmentation. \r\n", "--Can take some time in large disks. Requires elevated privileges.\r\n", "--See https://support.microsoft.com/help/3195161/defragmenting-sql-server-database-disk-drives\r\n", "SELECT @diskfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfrag to ON if you want to check for index fragmentation. \r\n", "--Can take some time to collect data depending on number of databases and indexes, as well as the scan mode chosen in @ixfragscanmode.\r\n", "SELECT @ixfrag = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @ixfragscanmode to the scanning mode you prefer. \r\n", "-- More detail on scanning modes available at https://docs.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql\r\n", "SELECT @ixfragscanmode = \u0027LIMITED\u0027 --(Valid inputs are DEFAULT, NULL, LIMITED, SAMPLED, or DETAILED. The default (NULL) is LIMITED)\r\n", "-- Set @bpool_consumer to OFF if you want to list what are the Buffer Pool Consumers from Buffer Descriptors. \r\n", "-- Mind that it may take some time in servers with large caches.\r\n", "SELECT @bpool_consumer = 1 -- 1 for ON 0 for OFF\r\n", "-- Set @spn_check to OFF if you want to skip SPN checks.\r\n", "SELECT @spn_check = 0 --(1 = ON; 0 = OFF)\r\n", "-- Set @gen_scripts to ON if you want to generate index related scripts.\r\n", "-- These include drops for Duplicate, Redundant, Hypothetical and Rarely Used indexes, as well as creation statements for FK and Missing Indexes.\r\n", "SELECT @gen_scripts = 0 -- 1 for enable 0 for disable\r\n", "-- Set @allow_xpcmdshell to OFF if you want to skip checks that are dependant on xp_cmdshell. \r\n", "-- Note that original server setting for xp_cmdshell would be left unchanged if tests were allowed.\r\n", "SELECT @allow_xpcmdshell = 1 -- 1 for enable 0 for disable\r\n", "-- Set @custompath below and set the custom desired path for .ps1 files. \r\n", "-- If not, default location for .ps1 files is the Log folder.\r\n", "SELECT @custompath = NULL\r\n", "-- These values are gathered for when they are needed\r\n", "SELECT @langid = lcid FROM sys.syslanguages WHERE name = @@LANGUAGE\r\n", "SELECT @adhoc = CONVERT(bit, [value]) FROM sys.configurations WHERE [Name] = \u0027optimize for ad hoc workloads\u0027;\r\n", "SELECT @masterpid = principal_id FROM master.sys.database_principals (NOLOCK) WHERE sid = SUSER_SID()\r\n", "SELECT @instancename = CONVERT(VARCHAR(128),SERVERPROPERTY(\u0027InstanceName\u0027)) \r\n", "SELECT @server = RTRIM(CONVERT(VARCHAR(128), SERVERPROPERTY(\u0027MachineName\u0027)))\r\n", "SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) \u0026 0xff)\r\n", "SELECT @sqlminorver = CONVERT(int, (@@microsoftversion / 0x10000) \u0026 0xff)\r\n", "SELECT @sqlbuild = CONVERT(int, @@microsoftversion \u0026 0xffff)\r\n", "SELECT @clustered = CONVERT(bit,ISNULL(SERVERPROPERTY(\u0027IsClustered\u0027),0))\r\n", "-- There are some variables that get passed from one check to another. This is easy in the stored procedure but won\u0027t work in the Notebook so we have to create a table in tempdb and read them from there\r\n", "IF NOT EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "CREATE TABLE tempdb.dbo.dbvars(VarName VarChar(256),VarValue VarChar(256))\r\n", "END\r\n", "SELECT @ostype = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ostype\u0027);\r\n", "SELECT @osver = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027osver\u0027);\r\n", "SELECT @affined_cpus = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027affined_cpus\u0027);\r\n", "SELECT @psavail = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027psavail\u0027);\r\n", "SELECT @accntsqlservice = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027accntsqlservice\u0027);\r\n", "SELECT @maxservermem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027maxservermem\u0027);\r\n", "SELECT @systemmem = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027systemmem\u0027);\r\n", "SELECT @mwthreads_count = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027mwthreads_count\u0027);\r\n", "SELECT @ifi = (SELECT VarValue FROM tempdb.dbo.dbvars WHERE VarName = \u0027ifi\u0027);\r\n", "IF @sqlmajorver > 10\r\n", "BEGIN\r\n", "DECLARE @IsHadrEnabled tinyint\r\n", "SELECT @IsHadrEnabled = CASE WHEN SERVERPROPERTY(\u0027EngineEdition\u0027) = 8 THEN 1 ELSE CONVERT(tinyint, SERVERPROPERTY(\u0027IsHadrEnabled\u0027)) END;\r\n", "END\r\n", "-- The T-SQL for the Check starts below\r\n", "RAISERROR (N\u0027Clearing up temporary objects\u0027, 10, 1) WITH NOWAIT\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbinfo\u0027)) \r\n", "DROP TABLE #dbinfo;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#output_dbinfo\u0027)) \r\n", "DROP TABLE #output_dbinfo;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIOStall\u0027)) \r\n", "DROP TABLE #tblIOStall;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs1\u0027)) \r\n", "DROP TABLE tempdb.dbo.tmpdbs1;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs0\u0027)) \r\n", "DROP TABLE tempdb.dbo.tmpdbs0;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerfCount\u0027)) \r\n", "DROP TABLE #tblPerfCount;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblPerfThresholds\u0027))\r\n", "DROP TABLE tempdb.dbo.tblPerfThresholds;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHypObj\u0027)) \r\n", "DROP TABLE #tblHypObj;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tblIxs1\u0027)) \r\n", "DROP TABLE tempdb.dbo.tblIxs1;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs2\u0027)) \r\n", "DROP TABLE #tblIxs2;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs3\u0027)) \r\n", "DROP TABLE #tblIxs3;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs4\u0027)) \r\n", "DROP TABLE #tblIxs4;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs5\u0027)) \r\n", "DROP TABLE #tblIxs5;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblIxs6\u0027)) \r\n", "DROP TABLE #tblIxs6;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFK\u0027)) \r\n", "DROP TABLE #tblFK;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dbcc\u0027)) \r\n", "DROP TABLE #dbcc;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#avail_logs\u0027)) \r\n", "DROP TABLE #avail_logs;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info1\u0027)) \r\n", "DROP TABLE #log_info1;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#log_info2\u0027)) \r\n", "DROP TABLE #log_info2;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpobjectnames\u0027))\r\n", "DROP TABLE #tmpobjectnames;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpfinalobjectnames\u0027))\r\n", "DROP TABLE #tmpfinalobjectnames;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWaits\u0027))\r\n", "DROP TABLE #tblWaits;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalWaits\u0027))\r\n", "DROP TABLE #tblFinalWaits;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblLatches\u0027))\r\n", "DROP TABLE #tblLatches;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalLatches\u0027))\r\n", "DROP TABLE #tblFinalLatches;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexCreation\u0027))\r\n", "DROP TABLE #IndexCreation;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#IndexRedundant\u0027))\r\n", "DROP TABLE #IndexRedundant;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblBlkChains\u0027))\r\n", "DROP TABLE #tblBlkChains;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsSamp\u0027))\r\n", "DROP TABLE #tblStatsSamp;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksBefore\u0027))\r\n", "DROP TABLE #tblSpinlocksBefore;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblSpinlocksAfter\u0027))\r\n", "DROP TABLE #tblSpinlocksAfter;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblFinalSpinlocks\u0027))\r\n", "DROP TABLE #tblFinalSpinlocks;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#pagerepair\u0027))\r\n", "DROP TABLE #pagerepair;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_io_virtual_file_stats\u0027))\r\n", "DROP TABLE #tmp_dm_io_virtual_file_stats;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_exec_query_stats\u0027)) \r\n", "DROP TABLE #tmp_dm_exec_query_stats;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#dm_exec_query_stats\u0027)) \r\n", "DROP TABLE #dm_exec_query_stats;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIOReq\u0027))\r\n", "DROP TABLE #tblPendingIOReq;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPendingIO\u0027))\r\n", "DROP TABLE #tblPendingIO;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#qpwarnings\u0027)) \r\n", "DROP TABLE #qpwarnings;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblStatsUpd\u0027))\r\n", "DROP TABLE #tblStatsUpd;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblPerSku\u0027))\r\n", "DROP TABLE #tblPerSku;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblColStoreIXs\u0027))\r\n", "DROP TABLE #tblColStoreIXs;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#SystemHealthSessionData\u0027))\r\n", "DROP TABLE #SystemHealthSessionData;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpdbfiledetail\u0027))\r\n", "DROP TABLE #tmpdbfiledetail;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblHints\u0027))\r\n", "DROP TABLE #tblHints;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTriggers\u0027))\r\n", "DROP TABLE #tblTriggers;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS\u0027))\r\n", "DROP TABLE #tmpIPS;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblCode\u0027))\r\n", "DROP TABLE #tblCode;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblWorking\u0027))\r\n", "DROP TABLE #tblWorking;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs_userchoice\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs_userchoice;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluNodesOutput\u0027))\r\n", "DROP TABLE #xp_cmdshell_CluNodesOutput;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_CluOutput\u0027))\r\n", "DROP TABLE #xp_cmdshell_CluOutput;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_Nodes\u0027))\r\n", "DROP TABLE #xp_cmdshell_Nodes;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEOutput\u0027))\r\n", "DROP TABLE #xp_cmdshell_QFEOutput;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_QFEFinal\u0027))\r\n", "DROP TABLE #xp_cmdshell_QFEFinal;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#RegResult\u0027))\r\n", "DROP TABLE #RegResult;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#ServiceStatus\u0027))\r\n", "DROP TABLE #ServiceStatus;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_AcctSPNoutput\u0027))\r\n", "DROP TABLE #xp_cmdshell_AcctSPNoutput;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#xp_cmdshell_DupSPNoutput\u0027))\r\n", "DROP TABLE #xp_cmdshell_DupSPNoutput;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#FinalDupSPN\u0027))\r\n", "DROP TABLE #FinalDupSPN;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#ScopedDupSPN\u0027))\r\n", "DROP TABLE #ScopedDupSPN;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDRI\u0027))\r\n", "DROP TABLE #tblDRI;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblInMemDBs\u0027))\r\n", "DROP TABLE #tblInMemDBs;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXIS\u0027))\r\n", "DROP TABLE #tmpXIS;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpXNCIS\u0027))\r\n", "DROP TABLE #tmpXNCIS;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmpIPS_CI\u0027))\r\n", "DROP TABLE #tmpIPS_CI;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tmp_dm_io_virtual_file_stats\u0027))\r\n", "DROP TABLE #tmp_dm_io_virtual_file_stats;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tmpdbsizes\u0027))\r\n", "DROP TABLE ##tmpdbsizes;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecated\u0027))\r\n", "DROP TABLE #tblDeprecated;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblDeprecatedJobs\u0027))\r\n", "DROP TABLE #tblDeprecatedJobs;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.##tblKeywords\u0027))\r\n", "DROP TABLE ##tblKeywords;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblQStoreInfo\u0027))\r\n", "DROP TABLE #tblQStoreInfo;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblAutoTuningInfo\u0027))\r\n", "DROP TABLE #tblAutoTuningInfo;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendationsCnt\u0027))\r\n", "DROP TABLE #tblTuningRecommendationsCnt;\r\n", "\tIF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.#tblTuningRecommendations\u0027))\r\n", "DROP TABLE #tblTuningRecommendations;\r\n", "IF EXISTS (SELECT [object_id]\r\n", "FROM tempdb.sys.objects (NOLOCK)\r\n", "WHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.dbvars\u0027))\r\n", "BEGIN\r\n", "\tDROP TABLE tempdb.dbo.dbvars\r\n", "END\r\n", "IF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.permstbl\u0027))\r\n", "\t\tBEGIN\r\n", "\t\t\tDROP TABLE tempdb.dbo.permstbl\r\n", "\t\tEND\r\n", "IF EXISTS (SELECT [object_id]\r\n", "\t\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\t\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.permstbl_msdb\u0027))\r\n", "\t\tBEGIN\r\n", "\t\t\tDROP TABLE tempdb.dbo.permstbl_msdb\r\n", "\t\tEND\r\n", "IF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs0\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs0;\r\n", "IF EXISTS (SELECT [object_id]\r\n", "\tFROM tempdb.sys.objects (NOLOCK)\r\n", "\tWHERE [object_id] = OBJECT_ID(\u0027tempdb.dbo.tmpdbs1\u0027))\r\n", "DROP TABLE tempdb.dbo.tmpdbs1;\r\n", "\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_perfctr\u0027\u0027)) DROP FUNCTION dbo.fn_perfctr\u0027)\r\n", "\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_allcols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_allcols\u0027)\r\n", "\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_keycols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_keycols\u0027)\r\n", "\tEXEC (\u0027USE tempdb; IF EXISTS (SELECT [object_id] FROM tempdb.sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(\u0027\u0027tempdb.dbo.fn_createindex_includecols\u0027\u0027)) DROP FUNCTION dbo.fn_createindex_includecols\u0027)\r\n", "\tRAISERROR (N\u0027All done!\u0027, 10, 1) WITH NOWAIT\r\n" ], "metadata": { "azdata_cell_guid": "e55e1dea-5448-42b1-85eb-22c3f4016956", "tags": [ "hide_input" ] }, "outputs": [ ], "execution_count": 0 } ] }