From afa27628818754e4c21755179dd168c999e5dbf9 Mon Sep 17 00:00:00 2001
From: Vlad Drumea <48413726+VladDBA@users.noreply.github.com>
Date: Wed, 5 Jun 2024 23:01:04 +0300
Subject: [PATCH] For #220, #221, #222
---
PSBlitz.ps1 | 17 +++--
Resources/GetIndexInfoForWholeDB.sql | 99 +++++++++++++++------------
Resources/GetStatsInfoForWholeDB.sql | 2 +-
Resources/PSBlitzOutput.xlsx | Bin 711718 -> 711764 bytes
4 files changed, 71 insertions(+), 47 deletions(-)
diff --git a/PSBlitz.ps1 b/PSBlitz.ps1
index 0207a61..a2d39be 100644
--- a/PSBlitz.ps1
+++ b/PSBlitz.ps1
@@ -256,8 +256,8 @@ param(
###Internal params
#Version
-$Vers = "4.1.1"
-$VersDate = "2024-06-04"
+$Vers = "4.1.2"
+$VersDate = "2024-06-05"
$TwoMonthsFromRelease = [datetime]::ParseExact("$VersDate", 'yyyy-MM-dd', $null).AddMonths(2)
$NowDate = Get-Date
#Get script path
@@ -1374,6 +1374,12 @@ if ($ToHTML -eq "Y") {
background-color: rgba(255, 255, 255, 0.7);
}
}
+ .IndexUsageTable{
+ td:nth-child(6) {
+ position: sticky; left: 0;
+ background-color: rgba(255, 255, 255, 0.7);
+ }
+ }
h1 {
text-align: center;
}
@@ -4798,6 +4804,8 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
@{Name = "Create Date"; Expression = { if ($_."Create Date" -ne [System.DBNull]::Value) { ($_."Create Date").ToString("yyyy-MM-dd HH:mm:ss") }else { $_."Create Date" } } },
@{Name = "Modify Date"; Expression = { if ($_."Modify Date" -ne [System.DBNull]::Value) { ($_."Modify Date").ToString("yyyy-MM-dd HH:mm:ss") }else { $_."Modify Date" } } },
"More Info" | ConvertTo-Html -As Table -Fragment
+ #add table specify style
+ $htmlTable = $htmlTable -replace '
', ''
}
$html = $HTMLPre + @"
@@ -5653,7 +5661,8 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
@{Name = "Object Name"; Expression = { $_."object_name" } },
@{Name = "Object Type"; Expression = { $_."object_type" } },
@{Name = "Index Name"; Expression = { $_."index_name" } },
- @{Name = "Index Type"; Expression = { $_."index_type" } },
+ @{Name = "Index Type"; Expression = { $_."index_type" } },
+ @{Name = "Partition"; Expression = {$_."partition_number"}},
@{Name = "Avg. Frag. %"; Expression = { $_."avg_frag_percent" } },
@{Name = "Page Count"; Expression = { $_."page_count" } },
@{Name = "Size in GB"; Expression = { $_."size_in_GB" } },
@@ -5694,7 +5703,7 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
$ExcelColNum = 1
$RowNum = 0
$DataSetCols = @("database", "object_name", "object_type", "index_name",
- "index_type", "avg_frag_percent", "page_count", "size_in_GB", "record_count","forwarded_record_count")
+ "index_type", "partition_number", "avg_frag_percent", "page_count", "size_in_GB", "record_count","forwarded_record_count")
if ($DebugInfo) {
Write-Host " ->Writing Stats results to sheet Index Fragmentation" -fore yellow
diff --git a/Resources/GetIndexInfoForWholeDB.sql b/Resources/GetIndexInfoForWholeDB.sql
index 7ec1295..0515322 100644
--- a/Resources/GetIndexInfoForWholeDB.sql
+++ b/Resources/GetIndexInfoForWholeDB.sql
@@ -9,47 +9,62 @@ SET NOCOUNT ON;
SET STATISTICS XML OFF;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- SELECT DB_NAME() AS [database],
- SCHEMA_NAME([obj].[schema_id]) + '.'
- + [obj].[name] AS [object_name],
- [obj].[type_desc] AS [object_type],
- ISNULL([ix].[name], '') AS [index_name],
- [ips].[index_type_desc] AS [index_type],
- SUM(CAST([ips].[avg_fragmentation_in_percent] AS DECIMAL(5, 2))) AS [avg_frag_percent],
- SUM([ips].[page_count]) AS [page_count],
- CAST(( CAST(SUM([ips].[page_count]) AS BIGINT) * 8 ) / 1024.00 / 1024.00 AS NUMERIC(20, 2)) AS [size_in_GB],
- SUM(CASE WHEN [ips].[alloc_unit_type_desc] = N'IN_ROW_DATA' THEN CAST([ips].[record_count] AS BIGINT) ELSE 0 END) AS [record_count],
- SUM([ips].[forwarded_record_count]) AS [forwarded_record_count]
- FROM [sys].[indexes] AS [ix]
- INNER JOIN [sys].[objects] AS [obj]
- ON [ix].[object_id] = [obj].[object_id]
- CROSS APPLY [sys].[dm_db_index_physical_stats](DB_ID(), [obj].[object_id], [ix].[index_id], NULL, 'SAMPLED') AS [ips]
- WHERE [ix].[type] IN(0, 1,2,3,4,5,6,7)
- AND [obj].[name] <> N'BlitzWho_AzureSQLDBReplace'
- AND [obj].[type] in ('U', 'V')
- AND [ips].[avg_fragmentation_in_percent] > 0
- /*only tables larger than ~400MB */
- AND [ips].[page_count] >= 52000
- AND obj.object_id not in
- (SELECT l.resource_associated_entity_id
- FROM sys.dm_tran_locks l
- WHERE l.request_mode = N'X'
- AND l.request_type = N'LOCK'
- AND l.resource_type = N'OBJECT'
- AND l.resource_database_id = DB_ID()
- GROUP BY l.resource_database_id,
- l.resource_associated_entity_id)
- GROUP BY SCHEMA_NAME([obj].[schema_id]) + '.'
- + [obj].[name], [obj].[type_desc], [ix].[name] , [ips].[index_type_desc]
- ORDER BY SUM(CAST([ips].[avg_fragmentation_in_percent] AS DECIMAL(5, 2))) DESC;
+IF OBJECT_ID('tempdb.dbo.#test', 'U') IS NOT NULL
+ DROP TABLE #test;
+SELECT [l].[resource_associated_entity_id]
+INTO #test
+FROM sys.[dm_tran_locks] [l]
+WHERE [l].[request_mode] = N'X'
+ AND [l].[request_type] = N'LOCK'
+ AND [l].[resource_type] = N'OBJECT'
+ AND [l].[resource_database_id] = DB_ID()
+GROUP BY [l].[resource_database_id],
+ [l].[resource_associated_entity_id];
- SELECT 'Exclusive Lock' AS [xlocked],
- OBJECT_NAME(l.resource_associated_entity_id) AS [object_name]
- FROM sys.dm_tran_locks l
- WHERE l.request_mode = N'X'
- AND l.request_type = N'LOCK'
- AND l.resource_type = N'OBJECT'
- AND l.resource_database_id = DB_ID()
- GROUP BY l.resource_database_id,
- l.resource_associated_entity_id;
\ No newline at end of file
+SELECT DB_NAME() AS [database],
+ SCHEMA_NAME([obj].[schema_id]) + '.'
+ + [obj].[name] AS [object_name],
+ [obj].[type_desc] AS [object_type],
+ ISNULL([ix].[name], '') AS [index_name],
+ [ips].[index_type_desc] AS [index_type],
+ [ips].[partition_number],
+ CAST([ips].[avg_fragmentation_in_percent] AS DECIMAL(5, 2)) AS [avg_frag_percent],
+ [ips].[page_count] AS [page_count],
+ CAST(( CAST([ips].[page_count] AS BIGINT) * 8 ) / 1024.00 / 1024.00 AS NUMERIC(20, 2)) AS [size_in_GB],
+ SUM(CASE
+ WHEN [ips].[alloc_unit_type_desc] = N'IN_ROW_DATA' THEN CAST([ips].[record_count] AS BIGINT)
+ ELSE 0
+ END) AS [record_count],
+ [ips].[forwarded_record_count] AS [forwarded_record_count]
+FROM [sys].[indexes] AS [ix]
+ INNER JOIN [sys].[objects] AS [obj]
+ ON [ix].[object_id] = [obj].[object_id]
+ CROSS APPLY [sys].[dm_db_index_physical_stats](DB_ID(), [obj].[object_id], [ix].[index_id], NULL, 'SAMPLED') AS [ips]
+WHERE [ix].[type] IN( 0, 1, 2, 3,
+ 4, 5, 6, 7 )
+ AND [ix].[is_disabled] = 0
+ AND [obj].[name] <> N'BlitzWho_AzureSQLDBReplace'
+ AND [obj].[type] IN ( 'U', 'V' )
+ /*AND [ips].[avg_fragmentation_in_percent] > 0*/
+ /*only tables larger than ~400MB */
+ AND [ips].[page_count] >= 52000
+ AND [obj].[object_id] NOT IN (SELECT [resource_associated_entity_id]
+ FROM #test)
+GROUP BY SCHEMA_NAME([obj].[schema_id]) + '.'
+ + [obj].[name],
+ [obj].[type_desc],
+ [ix].[name],
+ [ips].[index_type_desc],
+ [ips].[partition_number],
+ [ips].[avg_fragmentation_in_percent],
+ [ips].[page_count],
+ [ips].[forwarded_record_count]
+ORDER BY [ips].[avg_fragmentation_in_percent] DESC;
+
+SELECT 'Exclusive Lock' AS [xlocked],
+ OBJECT_NAME([resource_associated_entity_id]) AS [object_name]
+FROM #test;
+
+IF OBJECT_ID('tempdb.dbo.#test', 'U') IS NOT NULL
+ DROP TABLE #test;
\ No newline at end of file
diff --git a/Resources/GetStatsInfoForWholeDB.sql b/Resources/GetStatsInfoForWholeDB.sql
index 0442127..10a47af 100644
--- a/Resources/GetStatsInfoForWholeDB.sql
+++ b/Resources/GetStatsInfoForWholeDB.sql
@@ -204,7 +204,7 @@ SET [update_table_stats] = CASE
ELSE NULL
END
-WHERE [id] IN(SELECT MAX([id])
+WHERE [id] IN(SELECT MIN([id])
FROM ##PSBlitzStatsInfo
GROUP BY [object_name]);
UPDATE ##PSBlitzStatsInfo SET [update_individual_stats] = CASE
diff --git a/Resources/PSBlitzOutput.xlsx b/Resources/PSBlitzOutput.xlsx
index 0182b9eaaccab23867e3a757e260c01b8c5bfb13..e44790a918cea2609463fb059d15daa50d21bc7c 100644
GIT binary patch
delta 25507
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