SQL Server Blog by Matt Wiedeman

Useful scripts for SQL Server administration

Home About Contact Appalachian Trail Blog
Ola Hallengren Reindex with Update Stats (Brent Ozar recommendation) January 2, 2026

Many years ago, SQL Server guru Brent Ozar provided his recommendations for the IndexOptimize stored procedure provided by another SQL Server guru, Ola Hallengren.

You can read it here

Here's what you need:

EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE',
@FragmentationLevel1 = 50,
@FragmentationLevel2 = 80,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'
SQL Server useful configuration settings January 2, 2026

Use this script to set default settings for your SQL Server:

USE [master]
GO
ALTER DATABASE [model] SET RECOVERY SIMPLE WITH NO_WAIT
GO
EXEC sys.sp_configure N'backup compression default', N'1'
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sys.sp_configure N'backup checksum default', N'1'
GO
RECONFIGURE WITH OVERRIDE
GO

EXEC msdb.dbo.sp_set_sqlagent_properties @alert_replace_runtime_tokens = 1
GO

/***** Enable Database Mail *****/
exec sp_configure 'show advanced options'
,1;
go
reconfigure
go
sp_configure 'Database Mail XPs'
,1;
go
reconfigure
go
sp_configure 'show advanced options', 1 ;
GO
RECONFIGURE ;
GO
sp_configure 'blocked process threshold', 20 ;
GO
RECONFIGURE ;
GO
exec msdb.dbo.sp_set_sqlagent_properties @jobhistory_max_rows = 10000
,@jobhistory_max_rows_per_job = 1000
go
EXEC msdb.dbo.sp_purge_jobhistory  @oldest_date='2023-05-08T10:42:57'
GO
sp_delete_backuphistory @oldest_date = '2023-05-08' 

--set the maximum memory to 75%
declare @maxMem int
select @maxMem = cast(round((.75 * physical_memory_kb / power(1024, 1)), 0) as int) 
from sys.dm_os_sys_info
exec sys.sp_configure N'max server memory (MB)'
,@maxMem
go

-- I got this script from the internet a long time ago
-- It's a useful guide to setting Max DOP

DECLARE @CoreCount int;
DECLARE @NumaNodes int;
SET @CoreCount = (SELECT i.cpu_count from sys.dm_os_sys_info i);
SET @NumaNodes = (
    SELECT MAX(c.memory_node_id) + 1 
    FROM sys.dm_os_memory_clerks c 
    WHERE memory_node_id < 64
    );
IF @CoreCount > 4 /* If less than 5 cores, don't bother. */
BEGIN
    DECLARE @MaxDOP int;
    /* 3/4 of Total Cores in Machine */
    SET @MaxDOP = @CoreCount * 0.75; 
    /* if @MaxDOP is greater than the per NUMA node
       Core Count, set @MaxDOP = per NUMA node core count
    */
    IF @MaxDOP > (@CoreCount / @NumaNodes) 
        SET @MaxDOP = (@CoreCount / @NumaNodes) * 0.75;
    /*
        Reduce @MaxDOP to an even number 
    */
    SET @MaxDOP = @MaxDOP - (@MaxDOP % 2);
    /* Cap MAXDOP at 8, according to Microsoft */
    IF @MaxDOP > 8 SET @MaxDOP = 8;
    PRINT 'Suggested MAXDOP = ' + CAST(@MaxDOP as varchar(max));
END
ELSE
BEGIN
    PRINT 'Suggested MAXDOP = 0 since you have less than 4 cores total.';
    PRINT 'This is the default setting, you likely do not need to do';
    PRINT 'anything.';
END
SQL Server configure SQL Mail January 2, 2026

 --Use this script to configure mail

use msdb
go
DECLARE @profile_name sysname,
        @account_name sysname,
        @SMTP_servername sysname,
        @email_address NVARCHAR(128),
    @display_name NVARCHAR(128);
-- Profile name. Replace with the name for your profile
        SET @profile_name = 'SQL Mail';
-- Account information. Replace with the information for your account.
SET @account_name = 'IT';
SET @SMTP_servername = 'xx.xxx.xx.xx';
SET @email_address = 'IT@yourcompany.com';
        SET @display_name = 'IT';

-- Verify the specified account and profile do not already exist.
IF EXISTS (SELECT * FROM msdb.dbo.sysmail_profile WHERE name = @profile_name)
BEGIN
  RAISERROR('The specified Database Mail profile (<profile_name,sysname,SampleProfile>) already exists.', 16, 1);
  GOTO done;
END;
IF EXISTS (SELECT * FROM msdb.dbo.sysmail_account WHERE name = @account_name )
BEGIN
 RAISERROR('The specified Database Mail account (<account_name,sysname,SampleAccount>) already exists.', 16, 1) ;
 GOTO done;
END;
-- Start a transaction before adding the account and the profile
BEGIN TRANSACTION ;
DECLARE @rv INT;
-- Add the account
EXECUTE @rv=msdb.dbo.sysmail_add_account_sp
    @account_name = @account_name,
    @email_address = @email_address,
    @display_name = @display_name,
    @mailserver_name = @SMTP_servername;
IF @rv<>0
BEGIN
    RAISERROR('Failed to create the specified Database Mail account (<account_name,sysname,SampleAccount>).', 16, 1) ;
    GOTO done;
END
-- Add the profile
EXECUTE @rv=msdb.dbo.sysmail_add_profile_sp
    @profile_name = @profile_name ;
IF @rv<>0
BEGIN
    RAISERROR('Failed to create the specified Database Mail profile (<profile_name,sysname,SampleProfile>).', 16, 1);
ROLLBACK TRANSACTION;
    GOTO done;
END;
-- Associate the account with the profile.
EXECUTE @rv=msdb.dbo.sysmail_add_profileaccount_sp
    @profile_name = @profile_name,
    @account_name = @account_name,
    @sequence_number = 1 ;
IF @rv<>0
BEGIN
    RAISERROR('Failed to associate the speficied profile with the specified account (<account_name,sysname,SampleAccount>).', 16, 1) ;
ROLLBACK TRANSACTION;
    GOTO done;
END;
COMMIT TRANSACTION;
done:
USE [msdb]
GO
EXEC msdb.dbo.sp_set_sqlagent_properties @email_save_in_sent_folder=1, 
@alert_replace_runtime_tokens=1, 
@databasemail_profile=N'SQL Mail', 
@use_databasemail=1
GO
GO
SQL Server Alerts January 2, 2026
--Use this to configure alerts in SQL Server
 use msdb
go
EXEC master.dbo.sp_MSsetalertinfo @failsafeoperator=N'', 
@notificationmethod=0
GO
/*
EXEC msdb.dbo.sp_add_alert @name=N'Severity 016',
@message_id=0,
@severity=16,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 016', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
*/
EXEC msdb.dbo.sp_add_alert @name=N'Severity 017',
@message_id=0,
@severity=17,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 017', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 018',
@message_id=0,
@severity=18,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 018', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 019',
@message_id=0,
@severity=19,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 019', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
/*
EXEC msdb.dbo.sp_add_alert @name=N'Severity 020',
@message_id=0,
@severity=20,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 020', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
*/
EXEC msdb.dbo.sp_add_alert @name=N'Severity 021',
@message_id=0,
@severity=21,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 021', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 022',
@message_id=0,
@severity=22,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 022', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 023',
@message_id=0,
@severity=23,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 023', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 024',
@message_id=0,
@severity=24,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 024', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Severity 025',
@message_id=0,
@severity=25,
@enabled=1,
@delay_between_responses=60,
@include_event_description_in=1,
@job_id=N'00000000-0000-0000-0000-000000000000';
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Severity 025', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Error Number 823',
@message_id=823,
 @severity=0,
 @enabled=1,
 @delay_between_responses=60,
 @include_event_description_in=1,
 @job_id=N'00000000-0000-0000-0000-000000000000'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Error Number 823', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Error Number 824',
 @message_id=824,
 @severity=0,
 @enabled=1,
 @delay_between_responses=60,
 @include_event_description_in=1,
 @job_id=N'00000000-0000-0000-0000-000000000000'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Error Number 824', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Error Number 825',
 @message_id=825,
 @severity=0,
 @enabled=1,
 @delay_between_responses=60,
 @include_event_description_in=1,
 @job_id=N'00000000-0000-0000-0000-000000000000'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Error Number 825', @operator_name=N'ITInfrastructure', @notification_method = 1;
GO
EXEC msdb.dbo.sp_add_alert @name=N'Error Number 8628', 
@message_id=8628, 
@severity=0, 
@enabled=1, 
@delay_between_responses=0, 
@include_event_description_in=0, 
@job_id=N'00000000-0000-0000-0000-000000000000'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Error Number 8628', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
EXEC master.dbo.sp_MSsetalertinfo @failsafeoperator=N'ITInfrastructure', 
@notificationmethod=3
GO
EXEC msdb.dbo.sp_add_alert @name=N'Blocking', 
@enabled=1, 
@delay_between_responses=600, 
@include_event_description_in=1, 
@performance_condition=N'SQLServer:General Statistics|Processes blocked||>|10', 
@job_id=N'00000000-0000-0000-0000-000000000000'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Blocking', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
USE [msdb]
GO
/****** Object:  Alert [Insufficient Disk Space 1101]    Script Date: 11/13/2018 1:52:00 PM ******/
EXEC msdb.dbo.sp_add_alert @name=N'Insufficient Disk Space 1101', 
@message_id=1101, 
@severity=0, 
@enabled=1, 
@delay_between_responses=1800, 
@include_event_description_in=1, 
@event_description_keyword=N'Insufficient Disk Space 1101', 
@category_name=N'[Uncategorized]'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Insufficient Disk Space 1101', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
USE [msdb]
GO
/****** Object:  Alert [Insufficient Disk Space 1105]    Script Date: 11/13/2018 1:52:09 PM ******/
EXEC msdb.dbo.sp_add_alert @name=N'Insufficient Disk Space 1105', 
@message_id=1105, 
@severity=0, 
@enabled=1, 
@delay_between_responses=1800, 
@include_event_description_in=1, 
@category_name=N'[Uncategorized]'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Insufficient Disk Space 1105', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
USE [msdb]
GO
/****** Object:  Alert [Insufficient Disk Space 9002]    Script Date: 11/13/2018 1:52:16 PM ******/
EXEC msdb.dbo.sp_add_alert @name=N'Insufficient Disk Space 9002', 
@message_id=9002, 
@severity=0, 
@enabled=1, 
@delay_between_responses=1800, 
@include_event_description_in=1, 
@event_description_keyword=N'Insufficient Disk Space 9002', 
@category_name=N'[Uncategorized]'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Insufficient Disk Space 9002', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
USE [msdb]
GO
/****** Object:  Alert [Transaction log is over 80% for TempDB]    Script Date: 11/13/2018 1:52:27 PM ******/
EXEC msdb.dbo.sp_add_alert @name=N'Transaction log is over 90% for TempDB', 
@message_id=0, 
@severity=0, 
@enabled=1, 
@delay_between_responses=600, 
@include_event_description_in=1, 
@category_name=N'[Uncategorized]', 
@performance_condition=N'Databases|Percent Log Used|tempdb|>|90'
GO
EXEC msdb.dbo.sp_add_notification @alert_name=N'Transaction log is over 90% for TempDB', @operator_name=N'ITInfrastructure', @notification_method = 1
GO
SQL Server Ola Hallengren jobs - Add notifications January 2, 2026

--Glen Berry posted this article with a script to schedule all the Ola Hallengren jobs. Highly recommended!


--Use this to update the Ola Hallengren jobs so that you can be alerted if one fails



use msdb

go

EXEC msdb.dbo.sp_update_job 

@job_name = 'CommandLog Cleanup', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'Output File Cleanup', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'sp_purge_jobhistory', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'DatabaseBackup - SYSTEM_DATABASES - FULL', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'DatabaseBackup - USER_DATABASES - FULL', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'DatabaseBackup - USER_DATABASES - LOG', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'DatabaseIntegrityCheck - SYSTEM_DATABASES', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'DatabaseIntegrityCheck - USER_DATABASES', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

EXEC msdb.dbo.sp_update_job 

@job_name = 'IndexOptimize - USER_DATABASES', 

@notify_level_email=2, 

@notify_email_operator_name=N'ITInfrastructure'

GO

Powershell disk space script January 2, 2026

This Powershell script monitors disk space on SQL Server hosts.



$smtpClient = New-Object System.Net.Mail.SmtpClient;
$smtpClient.Host = 'yourSMTPServer';
$smtpClient.Port = 25;
$list = $args[0] #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt
$computers = 'YourServerNameGoesHere'
#$computers = get-content $list #grab the names of the servers/computers to check from the list.txt file.
# Set free disk space threshold below in percent (default at 10%)
[decimal]$thresholdspace = 10
#assemble together all of the free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject  -ComputerName $computers Win32_LogicalDisk  `
| select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
| Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `
| ConvertTo-HTML -fragment 
$mail = new-object System.Net.Mail.MailMessage
$mail.From = "YourFromEmailGoesHere"
$mail.To.Add("YourToEmailGoesHere")
$mail.Subject = "Disk Space Monitoring Report"
# assemble the HTML for our body of the email report.
$HTMLmessage = @"

Disk Space Storage Report

This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed.
$tableFragment "@ $mail.Body = $HTMLmessage $mail.IsBodyHtml = 1 # Set up a regex search and match to look for any tags in our body. These would only be present if the script above found disks below the threshold of free space. # We use this regex matching method to determine whether or not we should send the email and report. $regexsubject = $HTMLmessage $regex = [regex] '(?im)' # if there was any row at all, send the email if ($regex.IsMatch($regexsubject)) { # send-mailmessage -from $fromemail -to $users -subject "Disk Space Monitoring Report" -BodyAsHTML -body $HTMLmessage -priority High -smtpServer $server # $smtpClient.Send($fromemail,$users,'Test Message', 'This is a test message.'); $smtpClient.Send($mail) } x

This query helps identify file growth issues.

Extract files from your SQL Server database January 2, 2026

This code is used to extract files stored in SQL Server



--To extract files from your SQL Server database

-- First,

sp_configure 'show advanced options', 1 
GO 
RECONFIGURE; 
GO 
-- Together with RECONFIGURE, enables Ole Automation system procedures so you can 
-- instantiate OLE objects within Transact-SQL batches.
sp_configure 'Ole Automation Procedures', 1 
GO 
RECONFIGURE; 
GO 
--Displays configured options so you can verify that Ole Automation Procedures is set to 1.
sp_configure 'show advanced options', 1

-- Now, this
USE [TWDEV]
Go --Asia banger!

DECLARE @outPutPath varchar(500) = 'c:\WindowsTEMP\'
, @i bigint
, @init int
, @data varbinary(max)
, @fPath varchar(max) 
, @folderPath  varchar(max)

--Get Data into temp Table variable so that we can iterate over it

DECLARE @Doctable TABLE (id int identity(1,1), [FileName]  varchar(2000), 
[Doc_Content] varBinary(max) )

INSERT INTO @Doctable([FileName], [Doc_Content])
/*
SELECT substring(pr_addtl_data.s_value,len(dbo.Pathfromfullname(pr_addtl_data.s_value))+2,len(pr_addtl_data.s_value))
,ls_value
FROM data_fields, pr_addtl_data 
WHERE data_fields.id = 84 AND pr_addtl_data.data_field_id = data_fields.id
*/
SELECT pr_addtl_data.s_value,ls_value
FROM data_fields, pr_addtl_data 
WHERE data_fields.id = 449 AND pr_addtl_data.data_field_id = data_fields.id
--select * from @Doctable

SELECT @i = COUNT(1) FROM @Doctable

WHILE @i >= 1

BEGIN

	SELECT
		 @data = [Doc_Content],
		 @fPath = @outPutPath + [FileName],
		 @folderPath = @outPutPath  
		FROM @Doctable WHERE id = @i
  
	  EXEC sp_OACreate 'ADODB.Stream', @init OUTPUT; -- An instace created
	  EXEC sp_OASetProperty @init, 'Type', 1; 
	  EXEC sp_OAMethod @init, 'Open'; -- Calling a method
	  EXEC sp_OAMethod @init, 'Write', NULL, @data; -- Calling a method
	  EXEC sp_OAMethod @init, 'SaveToFile', NULL, @fPath, 2; -- Calling a method
	  EXEC sp_OAMethod @init, 'Close'; -- Calling a method
	  EXEC sp_OADestroy @init; -- Closed the resources
  
	  print 'Document Generated at - '+  @fPath  
 
--Reset the variables for next use

	SELECT @data = NULL 
	, @init = NULL
	, @fPath = NULL 
	, @folderPath = NULL
	SET @i -= 1
END

Good luck!

xp_readerrorlog January 2, 2026

Use this to check the error log in SQL Server


--Use this to check the error log in SQL Server

-- You can filter out user names or errors

CREATE TABLE #xp_readerrorlog 
(
   LogDate Datetime,  
   ProcessInfo CHAR(15) NULL,  
   Text VARCHAR(max) NULL
) 
GO

INSERT INTO #xp_readerrorlog
EXEC xp_readerrorlog
GO

SELECT *
FROM #xp_readerrorlog
WHERE
text not like '%BACKUP%' and
text not like 'Database backed up%' and
text not like '%found 0 errors and repaired 0 errors%' and
text not like '%This is an informational message only%'
ORDER BY LogDate desc
GO

DROP TABLE #xp_readerrorlog 
GO

Good luck!

SQL Server - Top 10 tables in a database by size January 2, 2026

This code is used to find your top 10 tables in SQL Server



SELECT
t.name AS TableName,
s.name AS SchemaName,
p.rows,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.object_id = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.name NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.object_id > 255
GROUP BY
t.name, s.name, p.rows
ORDER BY
TotalSpaceMB DESC, t.name;

Good luck!

SQL Server - sysprocesses query January 2, 2026

I grabbed this code from a vendor a long time ago. Yes, there are many variations of sp_who out there. I like this one, though.


select EventTime = getdate(),
spid, blocked, 
ElapsedMinutes=datediff(ss,r.last_batch,getdate())/60.0,
waitresource, REPLACE(REPLACE(T.Text,char(10),' '), char(13),' ') as batch,
StmtText = case When b.TxtLen>0 then SUBSTRING(t.[Text],a.Pos, b.TxtLen) Else ' ' End,
DatabaseName = DB_Name(R.dbid),
m.grant_time, m.granted_memory_kb,
m.requested_memory_kb, m.required_memory_kb,
r.cpu, r.physical_io, r.lastwaittype, r.cmd, r.waittime, ex.Status,
p.query_Plan 
FROM sys.sysprocesses R
Left Outer Join sys.dm_exec_query_memory_grants m on m.session_id = r.spid
Left Outer Join sys.dm_exec_requests ex on ex.session_id = r.spid
Outer Apply sys.dm_exec_sql_text(R.sql_handle) t
Outer Apply (select query_plan from sys.dm_exec_query_plan(ex.plan_handle)) p
Outer Apply (select (r.stmt_start / 2) + 1) a(Pos)
Outer Apply (Select case r.stmt_end when -1 Then datalength(T.text) else r.stmt_end END - a.pos) b(TxtLen)
WHERE
1=1
and cmd <> 'AWAITING COMMAND'
and spid <> @@SPID
and spid > 50
and REPLACE(REPLACE(T.Text,char(10),' '), char(13),' ') is not NULL
ORDER BY ElapsedMinutes desc;

Good luck!

SQL Server - sysprocesses query January 2, 2026

This is a nice missing index query just because it builds the create index syntax for you. Who doesn't love that, right?


SELECT db.[name] as [DatabaseName]
	,id.object_id as [ObjectID]
	,OBJECT_NAME(id.[OBJECT_ID])
	,db.[database_id] as ObjectName
	,id.statement as FullyQualifideObjectName
	,id.equality_columns as EqualityColumns
	,id.inequality_columns as InequaltyColumns
	,gs.unique_compiles Uniquecompiles
	,gs.user_seeks as UserSeeks
	,gs.user_scans as UserScans
	,gs.last_user_seek as LastUserSeek
	,gs.last_user_scan as LastUserScan
	,gs.avg_total_user_cost as AvgTotalUserCost
	,gs.avg_total_system_cost as AvgTotalSystemCost
	,gs.avg_system_impact as AvgSystemImpact
	,gs.user_seeks * gs.avg_total_user_cost * (gs.avg_user_impact *.01) as IndexAdvantage
	,'CREATE INDEX [INX_' + OBJECT_NAME(id.object_id, db.database_id) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(id.equality_columns,''),',','_'),'[',''),']','') +
	CASE
	WHEN id.equality_columns is not null AND id.inequality_columns is not null
	THEN '_'
	ELSE ''
	END + REPLACE(REPLACE(REPLACE(ISNULL(id.inequality_columns,''),',','_'),'[',''),']','') +
	+ LEFT(CAST(NEWID() AS [nvarchar](64)),5) + '] ON ' + id.statement + ' (' + ISNULL(id.equality_columns, '') +
	CASE
	WHEN id.equality_columns IS NOT NULL AND id.inequality_columns is not null
	THEN ','
	ELSE ''
	END + ISNULL(id.inequality_columns,'') + ')' + ISNULL (' INCLUDE (' + id.included_columns + ')','') as ProposedIndex
	,CAST(CURRENT_TIMESTAMP as [smalldatetime]) as CollectionDate
FROM sys.dm_db_missing_index_group_stats AS gs WITH (NOLOCK) 
INNER JOIN sys.dm_db_missing_index_groups AS ig WITH(NOLOCK) ON ig.index_group_handle = gs.group_handle 
INNER JOIN sys.dm_db_missing_index_details AS id WITH (NOLOCK) ON ig.index_handle = id.index_handle 
INNER JOIN sys.databases db on db.database_id = id.database_id
WHERE db.[database_id] = DB_ID()
ORDER BY gs.user_seeks * gs.avg_total_user_cost * (gs.avg_user_impact *.01) DESC OPTION (RECOMPILE);

Good luck!