Skip to content

Instantly share code, notes, and snippets.

@paschott
Last active November 15, 2022 19:09
Show Gist options
  • Save paschott/4e5cccd1d014063496b6039d276e6c3a to your computer and use it in GitHub Desktop.
Save paschott/4e5cccd1d014063496b6039d276e6c3a to your computer and use it in GitHub Desktop.
Steps through all Azure SQLDB Servers and databases to find user-specific index usage
import-module az.sql
import-module az.resources
import-module importexcel
# Update-AzConfig -DisplayBreakingChangeWarning $false
# sign in to Azure account
Connect-AzAccount
#Folder containing sql script and place to create Excel file
$sourceFolder = "C:\SourceCode\AzureSQLDB UnusedDatabases\"
$ExcelFile = $sourceFolder + "DatabaseUsage.xlsx"
Remove-Item $ExcelFile -ErrorAction SilentlyContinue
$query = Get-Content ($sourceFolder + "User_Index_Usage.sql") -Raw
#Get Access Token to connect to SQL Servers
$AccessToken = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
#get current resource groups
$rg = Get-AzResourceGroup
foreach ($rgname in $rg.ResourceGroupName) {
$servers = Get-AzSqlServer -ResourceGroupName $rgname
foreach ($servername in $servers.ServerName) {
#work with each database
$databases = Get-AzSqlDatabase -ResourceGroupName $rgname -ServerName $servername | Where-Object DatabaseName -ne "master"
foreach ($db in $databases.DatabaseName) {
$params = @{
'database' = $db
'serverInstance' = $servername + ".database.windows.net"
'AccessToken' = $AccessToken
'outputSqlErrors' = $true
'query' = $query
'EncryptConnection' = $true
}
$output = Invoke-SqlCmd @params -OutputAs DataRows
##May need to trim the worksheetname to something shorter if that will be referenced.
$output | Export-Excel -Path $ExcelFile -WorksheetName $servername -Append `
-ExcludeProperty @("ItemArray", "RowError", "RowState", "Table", "HasErrors") -AutoSize -AutoFilter -BoldTopRow
} #databases
} #servers
} #Resource Groups
select * FROM (
SELECT @@servername as ServerName, db_name() as DatabaseName, '' as ObjectName, '' as IndexName, 0 as IndexID, 0 as UserSeeks, 0 as UserScans, 0 as UserLookups, 0 as UserUpdates, 0 as TableRows
UNION
SELECT
@@servername as ServerName
, db_name() as DatabaseName
, o.name AS ObjectName
, i.name AS IndexName
, i.index_id AS IndexID
, dm_ius.user_seeks AS UserSeeks
, dm_ius.user_scans AS UserScans
, dm_ius.user_lookups AS UserLookups
, dm_ius.user_updates AS UserUpdates
, p.TableRows
FROM sys.dm_db_index_usage_stats dm_ius
INNER JOIN sys.indexes i ON i.index_id = dm_ius.index_id
AND dm_ius.OBJECT_ID = i.OBJECT_ID
INNER JOIN sys.objects o ON dm_ius.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN (SELECT SUM(p.rows) TableRows, p.index_id, p.OBJECT_ID
FROM sys.partitions p GROUP BY p.index_id, p.OBJECT_ID) p
ON p.index_id = dm_ius.index_id AND dm_ius.OBJECT_ID = p.OBJECT_ID
WHERE OBJECTPROPERTY(dm_ius.OBJECT_ID,'IsUserTable') = 1
AND dm_ius.database_id = DB_ID()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
and NOT (user_lookups = 0 and user_scans = 0 and user_seeks = 0 and user_updates = 0)
) as t
ORDER BY UserSeeks + UserScans + UserLookups ASC
GO
@paschott
Copy link
Author

With thanks to Pinal Dave for the Index query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment