diff --git a/database-get-checkdb-history.sql b/database-get-checkdb-history.sql new file mode 100644 index 0000000..55a9ed6 --- /dev/null +++ b/database-get-checkdb-history.sql @@ -0,0 +1,19 @@ +DECLARE @default_trace_path VARCHAR(500) + ,@tracefilename VARCHAR(500) + ,@indx INT; + +SET @default_trace_path = (SELECT path FROM sys.traces WHERE is_default = 1); +SET @default_trace_path = REVERSE(@default_trace_path); +SELECT @indx = PATINDEX('%\%', @default_trace_path); +SET @default_trace_path = REVERSE(@default_trace_path); +SET @tracefilename = LEFT( @default_trace_path,LEN(@default_trace_path) - @indx) + '\log.trc'; + +SELECT SUBSTRING(CONVERT(NVARCHAR(MAX),TEXTData),36, PATINDEX('%executed%',TEXTData)-36) [Command] + ,LoginName + ,StartTime + ,CONVERT(INT,SUBSTRING(CONVERT(NVARCHAR(MAX),TEXTData),PATINDEX('%found%',TEXTData)+6,PATINDEX('%errors %',TEXTData)-PATINDEX('%found%',TEXTData)-6)) [Errors], CONVERT(INT,SUBSTRING(CONVERT(NVARCHAR(MAX),TEXTData),PATINDEX('%repaired%',TEXTData)+9,PATINDEX('%errors.%',TEXTData)-PATINDEX('%repaired%',TEXTData)-9)) [Repaired] + ,SUBSTRING(CONVERT(NVARCHAR(MAX),TEXTData),PATINDEX('%time:%',TEXTData)+6,PATINDEX('%hours%',TEXTData)-PATINDEX('%time:%',TEXTData)-6)+':'+SUBSTRING(CONVERT (NVARCHAR(MAX),TEXTData),PATINDEX('%hours%',TEXTData)+6,PATINDEX('%minutes%',TEXTData)-PATINDEX('%hours%',TEXTData)-6)+':'+SUBSTRING(CONVERT(NVARCHAR (MAX),TEXTData),PATINDEX('%minutes%',TEXTData)+8,PATINDEX('%seconds.%',TEXTData)-PATINDEX('%minutes%',TEXTData)-8) [Duration] +FROM ::fn_trace_gettable( @tracefilename, DEFAULT) +WHERE EventClass = 22 +AND SUBSTRING(TEXTData,36,12) = 'DBCC CHECKDB' +ORDER BY StartTime DESC; diff --git a/dynamic-pivot-query-example.sql b/dynamic-pivot-query-example.sql new file mode 100644 index 0000000..7088584 --- /dev/null +++ b/dynamic-pivot-query-example.sql @@ -0,0 +1,24 @@ +DECLARE @DynamicPivotQuery AS NVARCHAR(MAX) + ,@ColumnName AS NVARCHAR(MAX); +  +DROP TABLE IF EXISTS #CourseSales; +CREATE TABLE #CourseSales (Course VARCHAR(50), Year INT, Earning INT); +INSERT #CourseSales VALUES +('course_a',2020, 1), ('course_a',2021,2) +, ('course_b',2019,1), ('course_b',2020,2),('course_b',2021,3) +, ('course_c',2018,1), ('course_c',2019,2), ('course_c',2020,3),('course_c',2021,4) +, ('other',2019,2), ('other',2020,4), ('other',2021,6); + +--Get distinct values of the PIVOT Column(s) +SELECT @ColumnName= ISNULL(@ColumnName + ',','') + QUOTENAME(Course) +FROM (SELECT DISTINCT Course FROM #CourseSales) AS Courses; +  +--Prepare the PIVOT query using the dynamic value(s) +SET @DynamicPivotQuery = +  N'SELECT Year, ' + @ColumnName + ' +    FROM #CourseSales +    PIVOT(SUM(Earning)  +          FOR Course IN (' + @ColumnName + ')) AS PVTTable'; + +--Execute the Dynamic Pivot Query +EXEC sp_executesql @DynamicPivotQuery; \ No newline at end of file diff --git a/error-log-find-size-and-location.sql b/error-log-find-size-and-location.sql new file mode 100644 index 0000000..23310ac --- /dev/null +++ b/error-log-find-size-and-location.sql @@ -0,0 +1,19 @@ +DECLARE @logfiles TABLE ( + [FileArchive] TINYINT, + [Date] DATETIME, + [LogFileSizeB] BIGINT +); + +INSERT @logfiles +EXEC xp_enumerrorlogs; + +SELECT [FileArchive] + ,[Date] + ,CONVERT(VARCHAR(50),CAST(SUM(CAST([LogFileSizeB] AS FLOAT)) / 1024 / 1024 AS DECIMAL(10,4))) + ' MB' SizeMB +FROM @logfiles +GROUP BY [FileArchive] + ,[Date] + ,[LogFileSizeB]; + +-- to identify error log file location +SELECT SERVERPROPERTY('ErrorLogFileName') [Error_Log_Location]; diff --git a/index-get-detail-by-table.sql b/index-get-detail-by-table.sql index 050bab1..95e3753 100644 --- a/index-get-detail-by-table.sql +++ b/index-get-detail-by-table.sql @@ -2,7 +2,7 @@ SET NOCOUNT ON; DECLARE @DBId INT = DB_ID() ,@SchemaName sysname - ,@TblName sysname = N'TblName' + ,@TblName sysname = N'dbo.factloanresponseattribute' ,@TblId INT ,@MinFragmentation REAL = 5.0 -- Defaulted to 5% as recommended by MS in BOL ,@MinPageCount INT = 1000 -- Defaulted to 1000 pages as recommended by MS in BOL @@ -68,68 +68,68 @@ ORDER BY i.index_id OPTION (MAXDOP 2); /****** INDEX CATALOG BLOCK END ******/ -/****** INDEX SIZE BLOCK START ******/ -DECLARE @tmp_compression TABLE ( - object_name NVARCHAR(128) - ,schema_name NVARCHAR(128) - ,index_id INT PRIMARY KEY CLUSTERED - ,partition_number INT - ,size_with_current_compression_setting BIGINT - ,size_with_requested_compression_setting BIGINT - ,sample_size_with_current_compression_setting BIGINT - ,sample_size_with_requested_compression_setting BIGINT -); +--/****** INDEX SIZE BLOCK START ******/ +--DECLARE @tmp_compression TABLE ( +-- object_name NVARCHAR(128) +-- ,schema_name NVARCHAR(128) +-- ,index_id INT PRIMARY KEY CLUSTERED +-- ,partition_number INT +-- ,size_with_current_compression_setting BIGINT +-- ,size_with_requested_compression_setting BIGINT +-- ,sample_size_with_current_compression_setting BIGINT +-- ,sample_size_with_requested_compression_setting BIGINT +--); -IF @EstimateCompression = 1 - INSERT INTO @tmp_compression ( - object_name - ,schema_name - ,index_id - ,partition_number - ,size_with_current_compression_setting - ,size_with_requested_compression_setting - ,sample_size_with_current_compression_setting - ,sample_size_with_requested_compression_setting - ) - EXEC sys.sp_estimate_data_compression_savings - @schema_name = @SchemaName - ,@object_name = @TblName - ,@index_id = NULL - ,@partition_number = NULL - ,@data_compression = @CompressionType; +--IF @EstimateCompression = 1 +-- INSERT INTO @tmp_compression ( +-- object_name +-- ,schema_name +-- ,index_id +-- ,partition_number +-- ,size_with_current_compression_setting +-- ,size_with_requested_compression_setting +-- ,sample_size_with_current_compression_setting +-- ,sample_size_with_requested_compression_setting +-- ) +-- EXEC sys.sp_estimate_data_compression_savings +-- @schema_name = @SchemaName +-- ,@object_name = @TblName +-- ,@index_id = NULL +-- ,@partition_number = NULL +-- ,@data_compression = @CompressionType; -SELECT 'SIZE:' AS Info; -SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME(@TblId, @DBId) + '].[' + OBJECT_NAME(@TblId, @DBId) + ']' AS Object - ,i.name AS [Index] - ,i.type_desc AS [Index Type] - ,ps.alloc_unit_type_desc AS [Allocation Type] - ,CONVERT(NUMERIC(9, 2), ps.page_count * 8 * /*convert to MB*/ 0.000976562) AS [Index Size (MB)] - ,ps.page_count AS Pages - ,CONVERT(NUMERIC(5, 2), ps.avg_page_space_used_in_percent) AS [Avg Page Space Used (%)] - ,ps.record_count AS Records - ,ps.avg_record_size_in_bytes AS [Avg Record Size (bytes)] - ,ps.compressed_page_count AS [Compressed Pages] - ,CONVERT(NUMERIC(5, 2), tmp.size_with_requested_compression_setting * /*convert to MB*/ 0.000976562) AS [Est Compressed Size (MB)] - ,'ALTER INDEX [' + i.name + +'] ON ' + '[' + OBJECT_SCHEMA_NAME(@TblId, @DBId) + '].[' - + OBJECT_NAME(@TblId, @DBId) + ']' + ' REBUILD WITH ( FILLFACTOR = ' - + CONVERT( CHAR(3), CASE WHEN i.fill_factor = 0 THEN 100 - ELSE i.fill_factor - END - ) + ', ONLINE=ON, SORT_IN_TEMPDB=ON );' + ' UPDATE STATISTICS [' + OBJECT_SCHEMA_NAME(@TblId, @DBId) - + '].[' + OBJECT_NAME(@TblId, @DBId) + '] [' + i.name + +'];' AS [Rebuild Script] -FROM sys.dm_db_index_physical_stats(@DBId, @TblId, NULL, NULL, 'SAMPLED') AS ps - INNER JOIN sys.indexes i - ON ps.object_id = i.object_id - AND ps.index_id = i.index_id - LEFT OUTER JOIN @tmp_compression tmp - ON i.index_id = tmp.index_id -WHERE i.object_id = @TblId -AND i.is_disabled = 0 -AND i.is_hypothetical = 0 -ORDER BY i.index_id - ,i.name -OPTION (MAXDOP 2); -/****** INDEX SIZE BLOCK END ******/ +--SELECT 'SIZE:' AS Info; +--SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME(@TblId, @DBId) + '].[' + OBJECT_NAME(@TblId, @DBId) + ']' AS Object +-- ,i.name AS [Index] +-- ,i.type_desc AS [Index Type] +-- ,ps.alloc_unit_type_desc AS [Allocation Type] +-- ,CONVERT(NUMERIC(9, 2), ps.page_count * 8 * /*convert to MB*/ 0.000976562) AS [Index Size (MB)] +-- ,ps.page_count AS Pages +-- ,CONVERT(NUMERIC(5, 2), ps.avg_page_space_used_in_percent) AS [Avg Page Space Used (%)] +-- ,ps.record_count AS Records +-- ,ps.avg_record_size_in_bytes AS [Avg Record Size (bytes)] +-- ,ps.compressed_page_count AS [Compressed Pages] +-- ,CONVERT(NUMERIC(5, 2), tmp.size_with_requested_compression_setting * /*convert to MB*/ 0.000976562) AS [Est Compressed Size (MB)] +-- ,'ALTER INDEX [' + i.name + +'] ON ' + '[' + OBJECT_SCHEMA_NAME(@TblId, @DBId) + '].[' +-- + OBJECT_NAME(@TblId, @DBId) + ']' + ' REBUILD WITH ( FILLFACTOR = ' +-- + CONVERT( CHAR(3), CASE WHEN i.fill_factor = 0 THEN 100 +-- ELSE i.fill_factor +-- END +-- ) + ', ONLINE=ON, SORT_IN_TEMPDB=ON );' + ' UPDATE STATISTICS [' + OBJECT_SCHEMA_NAME(@TblId, @DBId) +-- + '].[' + OBJECT_NAME(@TblId, @DBId) + '] [' + i.name + +'];' AS [Rebuild Script] +--FROM sys.dm_db_index_physical_stats(@DBId, @TblId, NULL, NULL, 'SAMPLED') AS ps +-- INNER JOIN sys.indexes i +-- ON ps.object_id = i.object_id +-- AND ps.index_id = i.index_id +-- LEFT OUTER JOIN @tmp_compression tmp +-- ON i.index_id = tmp.index_id +--WHERE i.object_id = @TblId +--AND i.is_disabled = 0 +--AND i.is_hypothetical = 0 +--ORDER BY i.index_id +-- ,i.name +--OPTION (MAXDOP 2); +--/****** INDEX SIZE BLOCK END ******/ /****** POSSIBLE MISSING INDEXES BLOCK START ******/ SELECT 'POSSIBLE MISSING (since last restart):' AS Info; diff --git a/mysql-procedure-template.sql b/mysql-procedure-template.sql new file mode 100644 index 0000000..b046656 --- /dev/null +++ b/mysql-procedure-template.sql @@ -0,0 +1,11 @@ +USE ; + +DELIMITER // + +CREATE PROCEDURE () +BEGIN + SELECT + FROM ; +END // + +DELIMITER ; diff --git a/mysql-trigger-template.sql b/mysql-trigger-template.sql new file mode 100644 index 0000000..3232606 --- /dev/null +++ b/mysql-trigger-template.sql @@ -0,0 +1,14 @@ +USE ; + +DELIMITER // + +CREATE TRIGGER +AFTER INSERT +ON
FOR EACH ROW +BEGIN + UPDATE
+ SET = + WHERE = NEW. +END; + +DELIMITER ; diff --git a/plan-cache-find-longest-running-queries.sql b/plan-cache-find-longest-running-queries.sql index 5a66f91..4eff906 100644 --- a/plan-cache-find-longest-running-queries.sql +++ b/plan-cache-find-longest-running-queries.sql @@ -1,5 +1,5 @@ /* Execution plan cache */ -SELECT TOP (10) +SELECT TOP (1000) sqltext.text AS query ,querystats.execution_count ,querystats.max_elapsed_time @@ -13,4 +13,8 @@ FROM sys.dm_exec_query_stats as querystats CROSS APPLY sys.dm_exec_sql_text(querystats.sql_handle) AS sqltext ORDER BY querystats.max_elapsed_time DESC OPTION (RECOMPILE); -GO \ No newline at end of file +GO + +select * from sys.dm_exec_query_stats +where query_hash = 0x98714BE4E5BE6716 +or query_plan_hash = 0x98714BE4E5BE6716 \ No newline at end of file diff --git a/security-change-sql-login-password.sql b/security-change-sql-login-password.sql new file mode 100644 index 0000000..16ebd8f --- /dev/null +++ b/security-change-sql-login-password.sql @@ -0,0 +1,4 @@ +ALTER LOGIN [user] WITH + PASSWORD = 'NewPassword' + OLD_PASSWORD = 'OldPassword'; +GO \ No newline at end of file diff --git a/security-get-sql-server-password-age.sql b/security-get-sql-server-password-age.sql new file mode 100644 index 0000000..cc8711b --- /dev/null +++ b/security-get-sql-server-password-age.sql @@ -0,0 +1,5 @@ +-- Show all logins where the password is over 60 days old +SELECT name + ,LOGINPROPERTY([name], 'PasswordLastSetTime') AS 'PasswordChanged' +FROM sys.sql_logins +WHERE LOGINPROPERTY([name], 'PasswordLastSetTime') < DATEADD(dd, -60, GETDATE()); \ No newline at end of file diff --git a/security-migrate-server_principals.sql b/security-migrate-server_principals.sql index 8fe4850..dfaa9c1 100644 --- a/security-migrate-server_principals.sql +++ b/security-migrate-server_principals.sql @@ -1,6 +1,6 @@ -- Windows logins and groups -SELECT N'CREATE LOGIN [' + sp.name + '] FROM WINDOWS;' AS [-- Windows Logins to be Created --] +SELECT sp.name, 'IF NOT EXISTS (SELECT 1 FROM master.sys.server_principals WHERE name = ''' + sp.name + ''') BEGIN CREATE LOGIN [' + sp.name + '] FROM WINDOWS; END;' AS [-- Windows Logins to be Created --] FROM master.sys.server_principals AS sp WHERE sp.type IN ('U', 'G') AND sp.is_disabled = 0 @@ -8,7 +8,9 @@ AND sp.name NOT LIKE 'NT [AS]%\%' ORDER BY sp.name; -- SQL Server logins -SELECT N'CREATE LOGIN [' + sp.name + ']' +SELECT sp.name + ,'IF SUSER_ID(''' + sp.name + ''') IS NULL BEGIN' + + ' ' + 'CREATE LOGIN [' + sp.name + ']' + ' ' + 'WITH PASSWORD=0x' + CONVERT(NVARCHAR(MAX), l.password_hash, 2) + N' HASHED' + ' ' + ', CHECK_POLICY=' + CASE l.is_policy_checked @@ -22,7 +24,7 @@ SELECT N'CREATE LOGIN [' + sp.name + ']' END + ' ' + ', DEFAULT_DATABASE=[' + l.default_database_name + N']' + ' ' + ', SID=0x' + CONVERT(NVARCHAR(MAX), sp.sid, 2) - + N';' AS [-- SQL Server Logins to be Created --] + + N'; END;' AS [-- SQL Server Logins to be Created --] FROM master.sys.server_principals AS sp INNER JOIN master.sys.sql_logins AS l ON sp.sid = l.sid @@ -37,14 +39,17 @@ WHERE sp.principal_id >= 100 AND sp.type = 'R'; -- Server Role permissions -SELECT 'ALTER SERVER ROLE [' + sr.name + '] ADD MEMBER [' + sp.name + '];' AS [-- Server Roles to be Granted --] +SELECT sr.name AS role_name + ,sp.name AS login_name + ,'ALTER SERVER ROLE [' + sr.name + '] ADD MEMBER [' + sp.name + '];' AS [-- Server Roles to be Granted --] FROM master.sys.server_role_members rm JOIN master.sys.server_principals sr ON sr.principal_id = rm.role_principal_id JOIN master.sys.server_principals sp ON sp.principal_id = rm.member_principal_id WHERE sp.type IN ( 'S', 'U', 'G' ) AND sp.is_disabled = 0 AND sp.name NOT LIKE 'NT [AS]%\%' -AND sp.name <> 'sa'; +AND sp.name <> 'sa' +ORDER BY sr.name, sp.name; -- Server Level Permissions SELECT CASE diff --git a/server-get-io-database-level.sql b/server-get-io-database-level.sql new file mode 100644 index 0000000..604585f --- /dev/null +++ b/server-get-io-database-level.sql @@ -0,0 +1,44 @@ +/* +NOTE: sys.dm_io_virtual_file_stats counters are reset whenever the SQL Server service is started +*/ + +WITH AggregateIOStatistics AS ( + SELECT DB_NAME(database_id) AS [DB Name] + ,CAST(SUM(num_of_bytes_read)/1048576 AS DECIMAL(12, 2)) AS reads_in_mb + ,CAST(SUM(num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS writes_in_mb + ,CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb + FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS] + GROUP BY database_id +) +SELECT ROW_NUMBER() OVER(ORDER BY io_in_mb DESC) AS [I/O Rank] + ,[DB Name] + ,CAST(reads_in_mb/ SUM(reads_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [Read Percent] + ,reads_in_mb AS [Read I/O (MB)] + ,CAST(writes_in_mb/ SUM(writes_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [Write Percent] + ,writes_in_mb AS [Write I/O (MB)] + ,CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [I/O Percent] + ,io_in_mb AS [Total I/O (MB)] +FROM AggregateIOStatistics +ORDER BY [I/O Rank]; + + +SELECT DB_NAME(DB_ID()) AS [DB_Name] + ,DFS.name AS [Logical_Name] + ,DIVFS.[file_id] + ,DFS.physical_name AS [PH_Name] + ,DIVFS.num_of_reads + ,DIVFS.io_stall_read_ms + ,CAST(100. * DIVFS.io_stall_read_ms/(DIVFS.io_stall_read_ms + DIVFS.io_stall_write_ms) AS DECIMAL(10,1)) AS [IO_Stall_Reads_Pct] + ,CAST(DIVFS.num_of_bytes_read/1048576.0 AS DECIMAL(19, 2)) AS [MB Read] + ,CAST(100. * DIVFS.num_of_reads/(DIVFS.num_of_reads + DIVFS.num_of_writes) AS DECIMAL(10,1)) AS [# Reads Pct] + ,CAST(100. * DIVFS.num_of_bytes_read/(DIVFS.num_of_bytes_read + DIVFS.num_of_bytes_written) AS DECIMAL(10,1)) AS [Read Bytes Pct] + ,DIVFS.num_of_writes + ,DIVFS.io_stall_write_ms + ,CAST(100. * DIVFS.io_stall_write_ms/(DIVFS.io_stall_write_ms + DIVFS.io_stall_read_ms) AS DECIMAL(10,1)) AS [IO_Stall_Writes_Pct] + ,CAST(DIVFS.num_of_bytes_written/1048576.0 AS DECIMAL(19, 2)) AS [MB Written] + ,CAST(100. * DIVFS.num_of_writes/(DIVFS.num_of_reads + DIVFS.num_of_writes) AS DECIMAL(10,1)) AS [# Write Pct] + ,CAST(100. * DIVFS.num_of_bytes_written/(DIVFS.num_of_bytes_read + DIVFS.num_of_bytes_written) AS DECIMAL(10,1)) AS [Written Bytes Pct] + ,(DIVFS.num_of_reads + DIVFS.num_of_writes) AS [Writes + Reads] +FROM sys.dm_io_virtual_file_stats(DB_ID(), NULL) AS DIVFS + JOIN sys.database_files AS DFS WITH (NOLOCK) ON DIVFS.[file_id]= DFS.[file_id] +ORDER BY (DIVFS.num_of_reads + DIVFS.num_of_writes) DESC; diff --git a/server-get-io-snapshot.sql b/server-get-io-snapshot.sql new file mode 100644 index 0000000..0406fc3 --- /dev/null +++ b/server-get-io-snapshot.sql @@ -0,0 +1,101 @@ +/*============================================================================ + File: ShortPeriodIOLatencies.sql + + Summary: Short snapshot of I/O latencies + + SQL Server Versions: 2005 onwards +------------------------------------------------------------------------------ + Written by Paul S. Randal, SQLskills.com + + (c) 2014, SQLskills.com. All rights reserved. + + For more scripts and sample code, check out http://www.SQLskills.com + + You may alter this code for your own *non-commercial* purposes (e.g. in a + for-sale commercial tool). Use in your own environment is encouraged. + You may republish altered code as long as you include this copyright and + give due credit, but you must obtain prior permission before blogging + this code. + + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF + ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +============================================================================*/ + + +DROP TABLE IF EXISTS [##SQLskillsStats1]; +DROP TABLE IF EXISTS [##SQLskillsStats2]; +GO + +SELECT [database_id], [file_id], [num_of_reads], [io_stall_read_ms], + [num_of_writes], [io_stall_write_ms], [io_stall], + [num_of_bytes_read], [num_of_bytes_written], [file_handle] +INTO ##SQLskillsStats1 +FROM sys.dm_io_virtual_file_stats (NULL, NULL); +GO + +WAITFOR DELAY '00:00:10'; +GO + +SELECT [database_id], [file_id], [num_of_reads], [io_stall_read_ms], + [num_of_writes], [io_stall_write_ms], [io_stall], + [num_of_bytes_read], [num_of_bytes_written], [file_handle] +INTO ##SQLskillsStats2 +FROM sys.dm_io_virtual_file_stats (NULL, NULL); +GO + +WITH [DiffLatencies] AS ( +SELECT +-- Files that weren't in the first snapshot + [ts2].[database_id], + [ts2].[file_id], + [ts2].[num_of_reads], + [ts2].[io_stall_read_ms], + [ts2].[num_of_writes], + [ts2].[io_stall_write_ms], + [ts2].[io_stall], + [ts2].[num_of_bytes_read], + [ts2].[num_of_bytes_written] +FROM [##SQLskillsStats2] AS [ts2] + LEFT OUTER JOIN [##SQLskillsStats1] AS [ts1] ON [ts2].[file_handle] = [ts1].[file_handle] +WHERE [ts1].[file_handle] IS NULL +UNION +SELECT +-- Diff of latencies in both snapshots + [ts2].[database_id], + [ts2].[file_id], + [ts2].[num_of_reads] - [ts1].[num_of_reads] AS [num_of_reads], + [ts2].[io_stall_read_ms] - [ts1].[io_stall_read_ms] AS [io_stall_read_ms], + [ts2].[num_of_writes] - [ts1].[num_of_writes] AS [num_of_writes], + [ts2].[io_stall_write_ms] - [ts1].[io_stall_write_ms] AS [io_stall_write_ms], + [ts2].[io_stall] - [ts1].[io_stall] AS [io_stall], + [ts2].[num_of_bytes_read] - [ts1].[num_of_bytes_read] AS [num_of_bytes_read], + [ts2].[num_of_bytes_written] - [ts1].[num_of_bytes_written] AS [num_of_bytes_written] +FROM [##SQLskillsStats2] AS [ts2] + LEFT OUTER JOIN [##SQLskillsStats1] AS [ts1] ON [ts2].[file_handle] = [ts1].[file_handle] +WHERE [ts1].[file_handle] IS NOT NULL +) + +SELECT DB_NAME ([vfs].[database_id]) AS [DB] + ,LEFT ([mf].[physical_name], 2) AS [Drive] + ,[mf].[type_desc] + ,[num_of_reads] AS [Reads] + ,[num_of_writes] AS [Writes] + ,CASE WHEN [num_of_reads] = 0 THEN 0 ELSE ([io_stall_read_ms] / [num_of_reads]) END AS [ReadLatency(ms)] + ,CASE WHEN [num_of_writes] = 0 THEN 0 ELSE ([io_stall_write_ms] / [num_of_writes]) END AS [WriteLatency(ms)] + ,CASE WHEN [num_of_reads] = 0 THEN 0 ELSE ([num_of_bytes_read] / [num_of_reads]) END AS [AvgBPerRead] + ,CASE WHEN [num_of_writes] = 0 THEN 0 ELSE ([num_of_bytes_written] / [num_of_writes]) END AS [AvgBPerWrite] + ,[mf].[physical_name] +FROM [DiffLatencies] AS [vfs] + JOIN sys.master_files AS [mf] + ON [vfs].[database_id] = [mf].[database_id] + AND [vfs].[file_id] = [mf].[file_id] +--ORDER BY [ReadLatency(ms)] DESC; +ORDER BY [WriteLatency(ms)] DESC; +GO + +-- Cleanup +DROP TABLE IF EXISTS [##SQLskillsStats1]; +DROP TABLE IF EXISTS [##SQLskillsStats2]; +GO diff --git a/server-get-io-volume-level.sql b/server-get-io-volume-level.sql new file mode 100644 index 0000000..7907315 --- /dev/null +++ b/server-get-io-volume-level.sql @@ -0,0 +1,74 @@ +/* +If you ask SQLskills, we will tell you something along the lines of: + Excellent: < 1ms + Very good: < 5ms + Good: 5 – 10ms + Poor: 10 – 20ms + Bad: 20 – 100ms + Really bad: 100 – 500ms + OMG!: > 500ms + +If you are finding that read and write latencies are bad on your server, there are several places you can start looking for issues. This is not a comprehensive list but some guidance of where to start. +- Analyze your workload. Is your indexing strategy correct? Not having the proper indexes will lead to much more data being read from disk. Scans instead of seeks. +- Are your statistics up to date? Bad statistics can make for poor choices for execution plans. +- Do you have parameter sniffing issues that are causing poor execution plans? +- Is the buffer pool under memory pressure, for instance from a bloated plan cache? +- Any network issues? Is your SAN fabric performing correctly? Have your storage engineer validate pathing and network. +- Move the hot spots to different storage arrays. In some cases it may be a single database or just a few databases that are causing all the problems. Isolating them to a different set of disk, or faster high end disk such as SSD’s may be the best logical solution. +- Can you partition the database to move troublesome tables to different disk to spread the load? +*/ + +CREATE TABLE #DiskInformation ( + DISK_Drive CHAR(100) + ,DISK_num_of_reads BIGINT + ,DISK_io_stall_read_ms BIGINT + ,DISK_num_of_writes BIGINT + ,DISK_io_stall_write_ms BIGINT + ,DISK_num_of_bytes_read BIGINT + ,DISK_num_of_bytes_written BIGINT + ,DISK_io_stall BIGINT +); + +INSERT #DiskInformation (DISK_Drive, DISK_num_of_reads, DISK_io_stall_read_ms, DISK_num_of_writes, DISK_io_stall_write_ms, DISK_num_of_bytes_read, DISK_num_of_bytes_written, DISK_io_stall) +SELECT LEFT(UPPER(mf.physical_name), 2) AS DISK_Drive + ,SUM(num_of_reads) AS DISK_num_of_reads + ,SUM(io_stall_read_ms) AS DISK_io_stall_read_ms + ,SUM(num_of_writes) AS DISK_num_of_writes + ,SUM(io_stall_write_ms) AS DISK_io_stall_write_ms + ,SUM(num_of_bytes_read) AS DISK_num_of_bytes_read + ,SUM(num_of_bytes_written) AS DISK_num_of_bytes_written + ,SUM(io_stall) AS io_stall +FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs + INNER JOIN sys.master_files AS mf WITH (NOLOCK) + ON vfs.database_id = mf.database_id AND vfs.file_id = mf.file_id +GROUP BY LEFT(UPPER(mf.physical_name), 2); + +SELECT DISK_Drive + ,CASE + WHEN DISK_num_of_reads = 0 THEN 0 + ELSE (DISK_io_stall_read_ms/DISK_num_of_reads) + END AS [Read Latency] + ,CASE + WHEN DISK_io_stall_write_ms = 0 THEN 0 + ELSE (DISK_io_stall_write_ms/DISK_num_of_writes) + END AS [Write Latency] + ,CASE + WHEN (DISK_num_of_reads = 0 AND DISK_num_of_writes = 0) THEN 0 + ELSE (DISK_io_stall/(DISK_num_of_reads + DISK_num_of_writes)) + END AS [Overall Latency] + ,CASE + WHEN DISK_num_of_reads = 0 THEN 0 + ELSE (DISK_num_of_bytes_read/DISK_num_of_reads) + END AS [Avg Bytes/Read] + ,CASE + WHEN DISK_io_stall_write_ms = 0 THEN 0 + ELSE (DISK_num_of_bytes_written/DISK_num_of_writes) + END AS [Avg Bytes/Write] + ,CASE + WHEN (DISK_num_of_reads = 0 AND DISK_num_of_writes = 0) THEN 0 + ELSE ((DISK_num_of_bytes_read + DISK_num_of_bytes_written)/(DISK_num_of_reads + DISK_num_of_writes)) + END AS [Avg Bytes/Transfer] +from #DiskInformation +ORDER BY [Overall Latency] OPTION (RECOMPILE); + +DROP TABLE IF EXISTS #DiskInformation; diff --git a/server-grant-exec-sp_send_dbmail.sql b/server-grant-exec-sp_send_dbmail.sql new file mode 100644 index 0000000..6f3c2e6 --- /dev/null +++ b/server-grant-exec-sp_send_dbmail.sql @@ -0,0 +1,5 @@ + +EXEC msdb.dbo.sp_addrolemember + @rolename = 'DatabaseMailUserRole' + ,@membername = ''; +GO \ No newline at end of file diff --git a/sp_who_is_active-run-as-script.sql b/sp_who_is_active-run-as-script.sql index ba8f9f4..9f11e54 100644 --- a/sp_who_is_active-run-as-script.sql +++ b/sp_who_is_active-run-as-script.sql @@ -11,7 +11,7 @@ Who Is Active? v11.17 (2016-10-18) Feedback: mailto:amachanic@gmail.com5 Updates: http://whoisactive.com -kill 385; +kill 375; kill 171; kill 389; kill 383;