Sunday, 20 July 2025

SQLDBA-SQL Server 2025 Enhancements for Managing TempDB Growth

SQL Server 2025 Enhancements for Managing TempDB Growth

SQL Server 2025 is now in Public Preview, which means it's free to test and provide feedback on. However, it's not yet generally available (GA), so it's not supported for production environments at this stage.

One of the highlights of this release is the continued focus on TempDB improvements. I'm glad to see that both SQL Server 2022 and now 2025 have introduced notable enhancements in this area, which should help with performance and scalability.

 TempDB is a system database in SQL Server that manages temporary objects for all databases on a server. Because it is a shared resource, it can easily become a performance bottleneck, as well as an opportunity for a single database or even a single query to wreck SQL Server performance.

Because of this, administrators will often give TempDB plenty of space and put its files on the fastest storage available. Even with these precautions, it is still possible for a TempDB-hungry workload to hog space and resources that result in latency or timeouts for end users.

 SQL Server stores a variety of data that is temporary in nature. This data is used in query processing, as well as in managing isolation levels and transactions. To illustrate the variety of uses that TempDB has, the following is a list of many of the types of objects stored there:

  • Temporary tables & Table Variables
  • Temporary Stored Procedures
  • Cursors
  • Result sets returned by table-valued functions
  • Worktables and work files
  • Intermediate sort results
  • Index rebuilds that use the SORT_IN_TEMPDB option
  • Row versions and version stores

This list has grown significantly over the years as more features have been added to SQL server. Because TempDB is simply another database that is stored just like any other database, it can easily be a bottleneck and single-point-of-failure for a SQL Server.

If TempDB space is exhausted and subsequent queries/processes cannot allocate space, then they will fail. This is the worst-case scenario that will mean some amount of downtime or errors for an application relying on this SQL Server. Inconsistent behavior will persist until the TempDB problem is resolved.

Up until now, managing TempDB workloads was often a balance of:

  • Give TempDB more space/files
  • Write custom monitoring/management procedures to deal with runaway workloads

The first of these options is easy but can be expensive and become inadequate as workloads grow in both size and complexity. The second option requires extensive administrative experience and may be challenging to implement effectively.

A built-in option to assist managing TempDB is a welcome addition to SQL Server and one that could greatly aid administrators that are struggling with TempDB resource contention or queries that cause runaway TempDB growth.

 What You Should Monitor in TempDB

In TempDB, there are two things that you should be monitoring:

  • TempDB datafiles
  • TempDB logfiles

If either of them gets filled up, it can bring down the whole SQL Server instance. There is no control until now for the admins to stop any process from filling up the data or log files, unless manually intervened.

Issue - Uncontrolled Usage

One of the key challenges today is that any user with access can easily fill up TempDB and bring down the entire SQL Server instance.

For example, if someone with read access to a large user table decides to dump it into a temp table, there's a high risk that it could consume all TempDB data file space, causing the instance to crash.

 New in SQL Server 2025- Resource Governor for TempDB

To avoid the situation just explained above, in SQL Server 2025 introduces the ability to use Resource Governor to help manage TempDB resources automatically. This article dives into the new feature, how to configure it, and how it can effectively manage TempDB-heavy workloads.

Note that this article was written using SQL Server 2025 CTP2.0. If feature updates arrive that impact Resource Governor for TempDB, then this article will be updated accordingly, along with this note. Also, in previous versions of SQL Server, Resource Governor was an Enterprise Edition feature.

 

  • This restricts filling up TempDB datafile.
  • It can stop the operation once it crosses the set threshold.
  • Can be set per application or across all applications.

That being said, TempDB Resource Governor manages only data files and not log file.

So who/what manages TempDB logfile then?

New in SQL Server 2025- ADR Support in TempDB

ADR (Accelerated Database Recovery) is a feature introduced in SQL Server 2019, which speeds up database recovery for user databases.

Starting SQL Server 2025, ADR is available to enable in TempDB. It is expected to help with:

  • Aggressive log truncation
  • Instantaneous rollback of transactions in TempDB

But, it was enabled by default in Azure SQL in February, but rolled back in March 2025 due to performance degradation.


Brief Overview of Resource Governor

Resource Governor is a mature feature that debuted all the way back in SQL Server 2008. Because of the complexity of effectively managing workloads at runtime, there is a bit of a learning curve when implementing Resource Governor. The following is a quick guide to getting started, which will help us get ready to use it with TempDB. If you are already a Resource Governor pro, then feel free to skip ahead to the next section.

By default, Resource Governor is disabled. This can be seen visually in SQL Server Management Studio:

The feature may be enabled by executing the following T-SQL:

 

ALTER RESOURCE GOVERNOR RECONFIGURE;

 

If there were any previous active configurations in Resource Governor, then enabling it like this will re-enable all those prior settings.

Once enabled, there are three basic features that go into using it, each with a distinct purpose:

  • Resource Pools
  • Workload Groups
  • Classifier Functions

Resource Pools

A resource pool is a logical container for a server’s physical resources. By default, a server will contain an internal resource pool and a default resource pool. You may create more based on a server’s configuration and complexity.

For the simplest of applications, using the default resource pool is perfectly fine. For larger servers with multiple applications and SLAs, there may be a need to have multiple resource pools available to separately manage those different use-cases.

Note that all queries to configure resource governor are run against the master database.

The following T-SQL creates a new resource pool:

 USE master;

 CREATE RESOURCE POOL max_cpu_percent_memoery_percent

WITH

(   MAX_CPU_PERCENT = 75,

    MAX_MEMORY_PERCENT = 50);

 Note that this example limits CPU usage to 75% and memory usage to 50% for these workloads. This query returns details on all resource pools:

 SELECT * FROM sys.resource_governor_resource_pools

 The results show the default resource pools, as well as the one we just created:

 

Workload Groups

A workload group is linked to a resource pool and is used to classify sessions. If you are only using a single resource pool, then this is trivial, but if you are using multiple resource pools, then each workload group would correspond to an application or set of applications.

The following query creates a new workload group and assigns it to the resource pool created earlier:

 CREATE WORKLOAD GROUP max_cpu_percent_memoery_percent_Group

USING max_cpu_percent_memoery_percent;

 Another DMV can be used to list the current workload groups defined on this server:

 SELECT *

FROM sys.resource_governor_workload_groups;

 The output shows the internal and default workload groups, as well as the one just created:

 Note that the statistics in this view are reset on server restart, but can also be reset using the following T-SQL:

 ALTER RESOURCE GOVERNOR RESET STATISTICS

 Classifier Functions

The last basic component of resource governor is the classifier function. These functions return the name of a workload group based on the session of the application’s connection. Its contents can be whatever is typically allowed in a scalar user-defined function, though it is generally preferable to keep things as simple as possible. Therefore, a simple IF/THEN/ELSE or CASE structure is ideal when possible.

The following is a simple classifier function that checks for a single app name and returns our DemoGroup workload group when matched. Otherwise, the default workload group is used:

 

USE master;

GO

 CREATE FUNCTION dbo.max_cpu_percent_memoery_percentClassifierFunction()

RETURNS SYSNAME

WITH SCHEMABINDING

AS

BEGIN

    IF (APP_NAME() = 'DemoApp')

BEGIN

        RETURN 'max_cpu_percent_memoery_percent_Group';

END

    RETURN 'default';

END;

  

Once created, a classifier function must be activated:

ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.max_cpu_percent_memoery_percentClassifierFunction);

ALTER RESOURCE GOVERNOR RECONFIGURE;

 The details of classifier functions can be pulled using another system view query:

SELECT

       resource_governor_configuration.classifier_function_id,

       resource_governor_configuration.is_enabled,

       objects.[name] AS function_name,

       sql_modules.[definition] AS function_definition

FROM sys.resource_governor_configuration

      INNER JOIN sys.objects

ON resource_governor_configuration.classifier_function_id = objects.[object_id]

      INNER JOIN sys.sql_modules

ON objects.[object_id] = sql_modules.[object_id];

  

The results show the basics of the function we created:

A close-up of a logo

AI-generated content may be incorrect.

  

The results confirm that the function is enabled, and the definition is added in for posterity. There are other columns available in each view that may be helpful for troubleshooting or documentation purposes, as well.

Note that the classifier function must be created in the master database. This ensures it is available for all connections and databases.

  

Configuring Resource Governor for TempDB

TempDB log space cannot be managed here – but that is OK! Why? Starting in SQL Server 2025, Accelerated Database Recovery (ADR) can be enabled on TempDB. The aggressive log truncation provided by ADR greatly reduces log space usage and churn in TempDB. Because TempDB is a temporary data store, the recovery aspects of ADR become irrelevant, making this an ideal feature to test and enable on TempDB!

Because Resource Governor has limited usage for TempDB, the amount of work needed to configure it is less than for other databases and metrics.

To begin, the default workload group will be adjusted to allow for a maximum of 20,000MB of data space for TempDB:

 

ALTER WORKLOAD GROUP [default] WITH (GROUP_MAX_TEMPDB_DATA_MB = 20000);

ALTER RESOURCE GOVERNOR RECONFIGURE;

 

Before Change:

This executes successfully and the resulting configuration change can be confirmed with this query:

 SELECT

group_id,

[name],

group_max_tempdb_data_mb

FROM sys.resource_governor_workload_groups;

 

This will return:



Joining a few views together allows for efficient review of both the configuration setting and usage for the default workgroup:

 

SELECT dm_resource_governor_workload_groups.group_id,

       dm_resource_governor_workload_groups.[name],

       resource_governor_workload_groups.group_max_tempdb_data_mb,

       dm_resource_governor_workload_groups.total_tempdb_data_limit_violation_count,

       dm_resource_governor_workload_groups.tempdb_data_space_kb,

       dm_resource_governor_workload_groups.peak_tempdb_data_space_kb

FROM sys.dm_resource_governor_workload_groups

      INNER JOIN sys.resource_governor_workload_groups

         ON dm_resource_governor_workload_groups.[name] =

                                resource_governor_workload_groups.[name]

WHERE dm_resource_governor_workload_groups.[name] = 'default';

 

 The results of this query are quite useful:

 

After change:

SELECT

group_id,

[name],

group_max_tempdb_data_mb

FROM sys.resource_governor_workload_groups;

 

 SELECT dm_resource_governor_workload_groups.group_id,

       dm_resource_governor_workload_groups.[name],

       resource_governor_workload_groups.group_max_tempdb_data_mb,

       dm_resource_governor_workload_groups.total_tempdb_data_limit_violation_count,

       dm_resource_governor_workload_groups.tempdb_data_space_kb,

       dm_resource_governor_workload_groups.peak_tempdb_data_space_kb

FROM sys.dm_resource_governor_workload_groups

      INNER JOIN sys.resource_governor_workload_groups

         ON dm_resource_governor_workload_groups.[name] =

                                resource_governor_workload_groups.[name]

WHERE dm_resource_governor_workload_groups.[name] = 'default';

A screenshot of a computer

AI-generated content may be incorrect.

 

Not only is the max TempDB data space setting shown here, but usage numbers are provided that indicate:

  • The current TempDB data space limit (tempdb_data_space_kb)
  • The maximum TempDB data space used since the last restart (peak_tempdb_data_space_kb)
  • The number of times the data space limit was exceeded, triggering the Resource Governor to end the transaction (total_tempdb_data_limit_violation_count)

Note that the usage numbers are in kilobytes, which I retained here to show granularity when usage was low.

 

Testing TempDB Resource Governor

To test TempDB resource governance, the workgroup, resource pool, and classifier function from earlier will be used. Note that the app name that will be routed to the DemoGroup is the app “DemoApp”. To actively query as this app, the connection will be changed from SQL Server Management Studio:

From the dialog window, the name of the app will be entered in the additional connection parameters:

A screenshot of a computer

AI-generated content may be incorrect.

When connected, the current app name and associated workload group can be verified with this T-SQL:

 

SELECT APP_NAME() AS AppName;

 

SELECT dm_resource_governor_workload_groups.[name] AS WorkloadGroupName

FROM sys.dm_exec_sessions

        INNER JOIN sys.dm_resource_governor_workload_groups

           ON dm_exec_sessions.group_id =

                           dm_resource_governor_workload_groups.group_id

WHERE dm_exec_sessions.session_id = @@SPID;

 

The results provide the expected result (phew!):

 

A screenshot of a computer

AI-generated content may be incorrect.

To make for a speedy demo, the DemoGroup will be adjusted to have a 2MB TempDB data space limit:

 

ALTER WORKLOAD GROUP max_cpu_percent_memoery_percent_Group WITH (GROUP_MAX_TEMPDB_DATA_MB = 2);

ALTER RESOURCE GOVERNOR RECONFIGURE;

 

 The following query verifies the current TempDB configuration for this workgroup:

 SELECT dm_resource_governor_workload_groups.group_id,

       dm_resource_governor_workload_groups.[name],

       resource_governor_workload_groups.group_max_tempdb_data_mb,

       dm_resource_governor_workload_groups.total_tempdb_data_limit_violation_count,

       dm_resource_governor_workload_groups.tempdb_data_space_kb,

       dm_resource_governor_workload_groups.peak_tempdb_data_space_kb

FROM sys.dm_resource_governor_workload_groups

      INNER JOIN sys.resource_governor_workload_groups

         ON dm_resource_governor_workload_groups.[name] =

                              resource_governor_workload_groups.[name]

WHERE dm_resource_governor_workload_groups.[name] = 'max_cpu_percent_memoery_percent_Group';

 

 The results are as follows:

A screenshot of a computer code

AI-generated content may be incorrect.

 

SELECT *

INTO #TempTableTest

FROM sys.sql_modules;

 

Msg 1138, Level 17, State 1, Line 27

Could not allocate a new page for database 'tempdb' because that would exceed the limit set for workload group 'max_cpu_percent_memoery_percent_Group'.

 

Completion time: 2025-07-20T11:25:13.8136436-04:00

 SELECT dm_resource_governor_workload_groups.group_id,

       dm_resource_governor_workload_groups.[name],

       resource_governor_workload_groups.group_max_tempdb_data_mb,

       dm_resource_governor_workload_groups.total_tempdb_data_limit_violation_count,

       dm_resource_governor_workload_groups.tempdb_data_space_kb,

       dm_resource_governor_workload_groups.peak_tempdb_data_space_kb

FROM sys.dm_resource_governor_workload_groups

      INNER JOIN sys.resource_governor_workload_groups

         ON dm_resource_governor_workload_groups.[name] =

                              resource_governor_workload_groups.[name]

WHERE dm_resource_governor_workload_groups.[name] = 'max_cpu_percent_memoery_percent_Group';

A screenshot of a computer program

AI-generated content may be incorrect.

 

The results show that the violation count has been incremented by one and that the peak TempDB data space used was exactly 2MB, which was the cap that was configured prior to this demo.

A fun additional query to run after the failure:

SELECT * FROM #TempTableTest;

The results are as follows:

A screen shot of a computer

AI-generated content may be incorrect.

  

This shows that the table contains nothing. WAIT! What table? Why does the temporary table exist if the SELECT INTO statement failed? This is, in fact, standard behavior and not an anomaly.

SELECT INTO is really the combination of CREATE TABLE and SELECT. The Resource Governor failure occurred during the SELECT portion of the query, after the temporary table was created. Therefore, if a TRY…CATCH attempts to recreate the table after the failure, the result will be an error indicating that the table already exists. This is a bit of an edge-case, but worth mentioning as it can impact more complex processes.

 

Disabling Resource Governor

As with any feature, there may be a need to disable part or all of it. This is (luckily) straightforward! To disable TempDB resource governance, the following T-SQL may be used:

 

                    ALTER WORKLOAD GROUP max_cpu_percent_memoery_percent_Group

WITH (GROUP_MAX_TEMPDB_DATA_MB = NULL);

 

This is run separately on each workload group. Therefore, if multiple workload groups are configured and in-use, be sure to disable TempDB resource governance on all that are no longer to be used for this purpose. All other Resource Governor features will continue to operate normally after this is executed.

Workload groups, resource pools, and classifier functions can be dropped when no longer needed. Ensure that they are dropped in an order such that no dependencies are violated. For example, if a workload group relies on a resource pool, then the workload group must be dropped first, prior to the resource pool.

The following script drops the various objects created during the demos in this article:

 

DROP WORKLOAD GROUP max_cpu_percent_memoery_percent_Group;

DROP RESOURCE POOL max_cpu_percent_memoery_percent;

DROP FUNCTION dbo.max_cpu_percent_memoery_percentClassifierFunction;

 

 

Oops! An error is thrown when this executes:

Msg 10920, Level 16, State 1, Line 59

Cannot drop user-defined function 'max_cpu_percent_memoery_percentClassifierFunction'. It is being used as a resource governor classifier.

 

Completion time: 2025-07-20T11:31:52.8001615-04:00

 

ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL);

RECONFIGURE

 

DROP FUNCTION dbo.DemoClassifierFunction

 

This results in glorious success! Finally, if there is a need to fully disable Resource Governor, that can be done like this:

ALTER RESOURCE GOVERNOR DISABLE;

Notes on Resource Governor for TempDB

 

Resource Governor for TempDB – Key Notes

SQL Server 2025 introduces enhancements to TempDB resource governance, offering administrators more flexibility and control:

Key Concepts

  • TempDB Space Configuration: TempDB files can be configured with static sizes or set to auto-grow, similar to user databases.
  • Limitations of Static Allocation: Relying solely on fixed space limits can be restrictive, especially when files are allowed to grow.
  • Percentage-Based Management: A more intuitive approach is to manage TempDB usage as a percentage of total or maximum space. For example, a query could be terminated if it exceeds 80% of TempDB usage.

Upcoming Enhancements

  • SQL Server 2025 (currently in Public Preview) is expected to support percentage-based space limits in Resource Governor, making TempDB management more dynamic and aligned with real-world usage patterns.
  • This feature is still evolving, and improvements are anticipated based on user feedback.

Conclusion

This update breathes new life into Resource Governor by simplifying TempDB management:

  • Reduces the need for custom scripts and manual monitoring.
  • Makes TempDB governance more accessible, even for those with limited SQL Server expertise.
  • Encourages adoption of out-of-the-box solutions that are easier to maintain.

Recommendation: Once on SQL Server 2025, try out this feature—especially if you’ve never actively managed TempDB space before. 

No comments:

Post a Comment

SQLDBA- Deadlock graph query

  Dead lock graph query DECLARE @xelfilepath NVARCHAR(260) SELECT @xelfilepath = dosdlc.path FROM sys.dm_os_server_diagnostics_log_configura...