sql server hub / tempdb guide

SQL Servertempdb guide

SQL Server uses tempdb for temporary objects, internal worktables, row versions, sorts, spills, and other work that does not belong in a user database.

Use this guide when tempdb growth, contention, version store, spills, slow jobs, or unclear pressure needs a clean technical check before anyone changes settings.

Guide

Guide~10 min readUpdated 19 Apr 2026

Share

LinkedInXEmail
  1. 01What SQL Server tempdb is used for
  2. 02SQL Server tempdb files and growth settings
  3. 03SQL Server tempdb sizing and file layout checks
  4. 04How to read SQL Server tempdb space usage
  5. 05How to find sessions using SQL Server tempdb
  6. 06SQL Server tempdb version store pressure
  7. 07SQL Server tempdb worktables and query spills
  8. 08SQL Server tempdb contention and PAGELATCH waits
  9. 09SQL Server tempdb storage latency and autogrowth risk
  10. 10What not to change in SQL Server tempdb
  11. 11When SQL Server tempdb issues need a health audit

What SQL Server tempdb is used for

SQL Server tempdb is a shared workspace for the whole instance. It holds user-created temporary objects, internal worktables, work files for sorts and hash joins, row-version store data, temp tables, table variables, cursor work, spool work, and other engine activity that does not belong in a user database.

That makes tempdb both configuration and workload. File count, size, growth, and storage path matter, but the pressure usually comes from sessions, queries, isolation choices, jobs, maintenance, spills, or concurrency patterns.

LayerWhat it answers
Files and configurationWhether tempdb has predictable file count, size, paths, and growth behavior.
Space usageWhether pressure is user objects, internal objects, version store, or free-space shortage.
Live consumersWhich sessions, tasks, jobs, hosts, or applications are allocating space now.
Waits and contentionWhether pressure is showing up as PAGELATCH waits, blocking, or another wait pattern.
Storage and growthWhether tempdb reads, writes, or autogrowth are part of the slow window.

SQL Server tempdb files and growth settings

Start with the current SQL Server tempdb file layout. Check data files and the log file separately, then review whether data files are equal enough, sized for the workload, and growing in controlled fixed-size increments.

A file-count change should be based on concurrency and contention data, not a generic rule. Growth settings should be boring enough that tempdb expansion does not become part of an incident.

On a new system without measured load, start conservatively with equally sized tempdb data files: often one file per logical processor up to 8 files, then stop and measure. If contention remains, add files in small groups and measure again. On a system with known load, use peak space, file usage, PAGELATCH waits, allocation contention, and storage latency before deciding whether 4, 8, or more files make sense.

SQL Server tempdb file layout

Lists tempdb file type, size, growth setting, max size, and physical path.

SELECT
    df.file_id,
    df.name AS logical_name,
    df.type_desc,
    df.physical_name,
    CONVERT(decimal(18,2), df.size / 128.0) AS size_mb,
    CASE
        WHEN df.is_percent_growth = 1
            THEN CONCAT(df.growth, N'%')
        ELSE CONCAT(CONVERT(decimal(18,2), df.growth / 128.0), N' MB')
    END AS growth_setting,
    CASE
        WHEN df.max_size = -1 THEN N'Unlimited'
        WHEN df.max_size = 0 THEN N'No growth'
        ELSE CONCAT(CONVERT(decimal(18,2), df.max_size / 128.0), N' MB')
    END AS max_size,
    df.is_percent_growth
FROM tempdb.sys.database_files AS df
ORDER BY df.type_desc, df.file_id;

Data files should usually be reviewed for equal sizing and sensible growth. For new workloads without measurements, a common starting point is one equally sized data file per logical processor up to 8 files. If contention remains after that, add files in small groups and measure again instead of jumping to one file per core. For known workloads, use contention, file usage, and latency data before adding more files. Percent growth can create unpredictable growth increments as files become large. Physical paths show whether tempdb is on the expected storage. A file layout mismatch is a review input, not an automatic reason to add files.

SQL Server tempdb sizing and file layout checks

SQL Server tempdb sizing should start from observed peak usage, not from a neat rule somebody remembers from another server. Check the busiest reporting, ETL, maintenance, index, and incident windows before deciding the steady-state size.

Once file count is in a sensible range, the next question is whether the configured size and growth behavior match real peaks. Tempdb is recreated on startup, so undersized files can turn a normal restart into a growth event at the worst time.

Put tempdb on fast storage when the workload uses it heavily, ideally separate from busy user database data and log volumes. If tempdb data files are spread across multiple volumes, keep the latency and capacity characteristics comparable so one slower path does not become the new bottleneck.

Sizing inputHow to use it
Observed peak spaceSize tempdb for real high-water marks plus headroom, not for the quiet snapshot.
Growth eventsFrequent growth means the starting size or growth increment is too small for the workload.
Storage placementPrefer fast, predictable storage for tempdb, separate from busy database and log volumes where the platform allows it.
Storage latencyHigh read or write stalls can make a correct size still feel slow.
ConcurrencyUse PAGELATCH and workload data before adding more files.
Restart behaviorTempdb is recreated on startup, so configured sizes must be intentional before restart.

How to read SQL Server tempdb space usage

Current space usage tells you which bucket is consuming SQL Server tempdb now. User objects, internal objects, version store, free space, and mixed extents point to different next checks.

Free space alone does not mean tempdb is healthy. A system can have free space and still be suffering from allocation contention, spills, bad growth behavior, uneven file use, or slow tempdb storage. Capture this during the pressure window when possible.

Current SQL Server tempdb space usage

Reads tempdb file space split into free space, user objects, internal objects, version store, and mixed extents.

USE tempdb;

SELECT
    df.file_id,
    df.name AS file_name,
    CONVERT(decimal(18,2), fs.total_page_count / 128.0) AS total_mb,
    CONVERT(decimal(18,2), fs.unallocated_extent_page_count / 128.0) AS free_mb,
    CONVERT(decimal(18,2), fs.user_object_reserved_page_count / 128.0) AS user_objects_mb,
    CONVERT(decimal(18,2), fs.internal_object_reserved_page_count / 128.0) AS internal_objects_mb,
    CONVERT(decimal(18,2), fs.version_store_reserved_page_count / 128.0) AS version_store_mb,
    CONVERT(decimal(18,2), fs.mixed_extent_page_count / 128.0) AS mixed_extents_mb
FROM sys.dm_db_file_space_usage AS fs
JOIN sys.database_files AS df
    ON df.file_id = fs.file_id
ORDER BY df.file_id;

user_objects_mb points toward temp tables, table variables, or explicit tempdb objects. internal_objects_mb points toward worktables, sort/hash work files, and internal engine work. version_store_mb points toward row versioning, snapshot behavior, or long transactions. free_mb is only one part of the picture; waits, latency, and growth history still matter. Uneven file usage can point back to file layout, growth history, or restart behavior.

How to find sessions using SQL Server tempdb

Session and task usage connect SQL Server tempdb consumption to real work. Session totals are useful for active connections, while task-level rows help when one request is currently allocating heavily.

These counters are best read during the problem window. After a request finishes, some task detail may disappear and the useful link back to query text can be lost. Use the output to decide whether the next check is a query plan, SQL Agent job, transaction, or application source.

Session-level tempdb usage

Shows tempdb allocations by session with host, application, login, status, and transaction count.

USE tempdb;

SELECT TOP (50)
    ssu.session_id,
    es.status,
    es.host_name,
    es.program_name,
    es.login_name,
    CONVERT(decimal(18,2),
        (ssu.user_objects_alloc_page_count - ssu.user_objects_dealloc_page_count) / 128.0
    ) AS user_objects_mb,
    CONVERT(decimal(18,2),
        (ssu.internal_objects_alloc_page_count - ssu.internal_objects_dealloc_page_count) / 128.0
    ) AS internal_objects_mb,
    es.open_transaction_count,
    es.last_request_start_time,
    es.last_request_end_time
FROM sys.dm_db_session_space_usage AS ssu
LEFT JOIN sys.dm_exec_sessions AS es
    ON es.session_id = ssu.session_id
WHERE ssu.session_id <> @@SPID
ORDER BY
    (ssu.user_objects_alloc_page_count - ssu.user_objects_dealloc_page_count)
  + (ssu.internal_objects_alloc_page_count - ssu.internal_objects_dealloc_page_count) DESC;

user_objects_mb points toward temp tables or explicit tempdb object use. internal_objects_mb points toward sort, hash, cursor, or worktable activity. program_name and host_name connect the usage to an application or job runner. Open transactions can keep work alive longer than expected.

Task and request tempdb usage

Shows task-level tempdb usage with active request status, waits, blocker, and running statement.

USE tempdb;

SELECT TOP (50)
    tsu.session_id,
    tsu.request_id,
    r.status,
    r.command,
    r.wait_type,
    r.wait_time,
    r.blocking_session_id,
    CONVERT(decimal(18,2),
        (tsu.user_objects_alloc_page_count - tsu.user_objects_dealloc_page_count) / 128.0
    ) AS task_user_objects_mb,
    CONVERT(decimal(18,2),
        (tsu.internal_objects_alloc_page_count - tsu.internal_objects_dealloc_page_count) / 128.0
    ) AS task_internal_objects_mb,
    SUBSTRING(
        sql_text.text,
        (r.statement_start_offset / 2) + 1,
        CASE
            WHEN r.statement_end_offset = -1
                THEN LEN(CONVERT(nvarchar(max), sql_text.text))
            ELSE (r.statement_end_offset - r.statement_start_offset) / 2 + 1
        END
    ) AS running_statement
FROM sys.dm_db_task_space_usage AS tsu
LEFT JOIN sys.dm_exec_requests AS r
    ON r.session_id = tsu.session_id
   AND r.request_id = tsu.request_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS sql_text
WHERE tsu.session_id <> @@SPID
ORDER BY
    (tsu.user_objects_alloc_page_count - tsu.user_objects_dealloc_page_count)
  + (tsu.internal_objects_alloc_page_count - tsu.internal_objects_dealloc_page_count) DESC;

task_internal_objects_mb is useful during active spill or worktable pressure. running_statement gives the next query or plan to inspect. wait_type and blocking_session_id help separate tempdb use from blocking. If one request dominates, check its plan, memory grant, and recent changes.

SQL Server tempdb version store pressure

Row-versioning features can reduce reader/writer conflicts, but they move work into SQL Server tempdb. Snapshot isolation, read committed snapshot, online operations, and long-running transactions can all make version store space grow.

Version store pressure should be checked by database, then tied back to transaction length, isolation settings, workload timing, and cleanup behavior. A long-running snapshot transaction can delay cleanup even after the query that created the versions has moved on.

SQL Server tempdb version-store usage by database

Shows how much tempdb space version-store records use for each database.

SELECT
    DB_NAME(vs.database_id) AS database_name,
    CONVERT(decimal(18,2), vs.reserved_page_count / 128.0) AS version_store_mb
FROM sys.dm_tran_version_store_space_usage AS vs
ORDER BY vs.reserved_page_count DESC;

version_store_mb shows which database is contributing version records. Rapid growth points toward row-versioning workload or long transactions. Low values are normal on systems not using much row versioning. If this grows during incidents, check active transactions and isolation choices next.

Long-running snapshot transactions

Shows active snapshot transactions that can keep version-store cleanup from catching up.

-- Run in the database where row-versioning pressure is suspected.
SELECT
    DB_NAME() AS database_name,
    transaction_id,
    transaction_sequence_num,
    commit_sequence_num,
    elapsed_time_seconds,
    session_id,
    is_snapshot,
    first_snapshot_sequence_num,
    max_version_chain_traversed,
    average_version_chain_traversed
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;

elapsed_time_seconds helps find transactions that have been alive long enough to delay cleanup. session_id connects the transaction to a connection that may need application or job context. High version-chain traversal can point toward expensive version-store reads. Use this together with version-store size by database, not as a standalone verdict.

SQL Server tempdb worktables and query spills

SQL Server can use tempdb for worktables and work files when sorts, hash joins, spools, cursors, or other operators need workspace. Execution plans may show this as a spill to tempdb when the operator did not get enough memory. That can be normal, but repeated spills usually need query-plan review.

Do not blame tempdb first. Check memory grants, estimates, statistics, indexes, row counts, and whether one report, ETL step, or maintenance job keeps pushing the same expensive query shape into tempdb. Use the SQL Server indexing guide when a poor access path widens the work, and the SQL Server slow performance guide when tempdb is only one symptom.

1

Look for sort, hash, spool, exchange, or worktable operators that spill during the slow window.

2

Check whether estimates are far from actual row counts before changing tempdb files.

3

Review memory grants, stale statistics, and missing or weak indexes.

4

Check the job, report, or application workflow that repeats the same tempdb-heavy shape.

SQL Server tempdb contention and PAGELATCH waits

SQL Server tempdb allocation contention often appears as PAGELATCH_UP, PAGELATCH_EX, or related latch waits against tempdb resources. This is different from storage I/O waits. It is latch contention on in-memory allocation pages, often under high temp object churn or concurrent workload pressure.

The fix depends on the pattern. File layout can matter, but so can query behavior, temp table churn, object design, workload timing, and SQL Server version.

Active waits pointing at tempdb

Shows active waiting tasks and requests where the wait resource or database points toward tempdb.

SELECT
    wt.session_id,
    wt.wait_type,
    wt.wait_duration_ms,
    wt.blocking_session_id,
    wt.resource_description,
    r.status,
    r.command,
    r.wait_resource,
    DB_NAME(r.database_id) AS database_name,
    s.host_name,
    s.program_name,
    s.login_name
FROM sys.dm_os_waiting_tasks AS wt
LEFT JOIN sys.dm_exec_requests AS r
    ON r.session_id = wt.session_id
LEFT JOIN sys.dm_exec_sessions AS s
    ON s.session_id = wt.session_id
WHERE wt.session_id <> @@SPID
  AND (
      wt.resource_description LIKE N'2:%'
      OR r.wait_resource LIKE N'2:%'
      OR r.database_id = 2
  )
ORDER BY wt.wait_duration_ms DESC;

PAGELATCH waits with tempdb resources can point to PFS, SGAM, or other allocation-page contention. wait_duration_ms shows whether the wait is momentary or building up. program_name and host_name help connect waits to a workload source. Check SQL Server version, temp object churn, and current file layout before adding more files. If blockers appear, continue with the blocking guide before changing tempdb.

SQL Server tempdb storage latency and autogrowth risk

SQL Server tempdb pressure can be allocation contention, space pressure, storage latency, or autogrowth at a bad time. File I/O stats help decide whether tempdb reads and writes are waiting on the storage path.

Job timing matters too. Maintenance, reporting, ETL, index work, and large loads can make tempdb look like the problem when the real issue is workload overlap. Correlate growth events, job history, monitoring data, and latency before moving files or changing file count.

SQL Server tempdb file latency

Reads read/write counts, stalls, and average latency for tempdb files.

SELECT
    mf.file_id,
    mf.name AS logical_name,
    mf.type_desc,
    vfs.num_of_reads,
    vfs.num_of_bytes_read,
    vfs.io_stall_read_ms,
    CONVERT(decimal(18,2),
        vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads, 0.0)
    ) AS avg_read_latency_ms,
    vfs.num_of_writes,
    vfs.num_of_bytes_written,
    vfs.io_stall_write_ms,
    CONVERT(decimal(18,2),
        vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0.0)
    ) AS avg_write_latency_ms
FROM sys.dm_io_virtual_file_stats(2, NULL) AS vfs
JOIN tempdb.sys.database_files AS mf
    ON mf.file_id = vfs.file_id
ORDER BY avg_write_latency_ms DESC, avg_read_latency_ms DESC;

avg_write_latency_ms matters because tempdb-heavy work can be write-sensitive. High stalls during pressure windows deserve storage and workload timing review. Compare data and log files separately. Latency numbers need context from monitoring, not one isolated snapshot.

SQL Agent job timing

Checks recent SQL Agent job steps when tempdb pressure may align with maintenance, reporting, or ETL work.

SELECT TOP (50)
    j.name AS job_name,
    h.step_id,
    h.step_name,
    h.run_status,
    DATETIMEFROMPARTS(
        h.run_date / 10000,
        (h.run_date % 10000) / 100,
        h.run_date % 100,
        h.run_time / 10000,
        (h.run_time % 10000) / 100,
        h.run_time % 100,
        0
    ) AS run_start_time,
    ((h.run_duration / 10000) * 3600)
      + (((h.run_duration % 10000) / 100) * 60)
      + (h.run_duration % 100) AS run_duration_seconds,
    h.message
FROM msdb.dbo.sysjobhistory AS h
JOIN msdb.dbo.sysjobs AS j
    ON j.job_id = h.job_id
WHERE h.step_id > 0
ORDER BY run_start_time DESC;

run_start_time lets you compare jobs with tempdb growth or wait spikes. run_duration_seconds helps find jobs overlapping the slow period. Long or failed steps may explain sudden tempdb pressure. If a job aligns with the incident, check its query plans, memory grants, and tempdb usage.

What not to change in SQL Server tempdb

SQL Server tempdb changes can require restarts, storage moves, workload timing, and rollback planning. Treat them as production changes, not small cosmetic cleanup.

1

Do not add too many tempdb files without contention data.

2

Do not shrink tempdb as routine cleanup.

3

Do not treat free space as enough to call tempdb healthy.

4

Do not use percent growth for large tempdb files.

5

Do not move tempdb or change growth settings without a rollback and restart plan.

6

Do not enable row-versioning isolation without checking tempdb capacity and version-store growth.

7

Do not blame tempdb for spills before checking query plans, memory grants, statistics, and indexes.

8

Do not rebuild indexes or run maintenance during a tempdb pressure incident unless the job is clearly the cause and can be safely stopped.

9

Do not ignore PAGELATCH waits pointing at tempdb allocation pages.

When SQL Server tempdb issues need a health audit

A health audit makes sense when SQL Server tempdb pressure is real but tied to other production checks: old file settings, weak monitoring, storage concern, blocking, maintenance overlap, row-versioning changes, or repeated slow periods.

Send tempdb file settings, current space usage, version-store output, session and task usage during pressure, waits, file latency, SQL Agent timing, monitoring data, and recent changes.

Next step

If tempdb is tied to backup, job, monitoring, storage, or blocking issues, use the SQL Server health audit page or request the audit above.

Next useful reads: the SQL Server health check guide for full-environment review, the SQL Server waits guide for wait interpretation, the SQL Server blocking guide for lock chains, the SQL Server indexing guide for plan and spill review, the SQL Server monitoring guide for recurring measurements, and the SQL Server sizing guide when tempdb pressure points back to capacity.