Chapter 08 · Storage Engine Internals: Pages, Extents, Heaps, B-Trees, and Transaction Log

8-KB Pages, Extents, Allocation Maps, IAM, PFS, GAM/SGAM, and File Internals

Connect ServiceHub rows to 8-KB pages, 64-KB extents, allocation maps, files, filegroups, and supported page-level evidence.

Advanced115–150 minutesStorage-layout + allocation labSQL Server 2025 CU7 · 17.0.4065.4Compatibility 170 · Developer/ExpressLast reviewed: August 2026

Learning outcomes

ServiceHub has reached the point where “the table is 40 MB” is no longer a sufficient storage explanation. Operators need to know what that number means physically: SQL Server stores ordinary rowstore data and indexes in 8-KB pages; eight contiguous pages form a 64-KB extent; allocation maps describe which extents and pages are available; and each table/index partition owns one or more allocation units. The goal is not to memorize page trivia. It is to connect supported metadata to concrete questions such as “which file is growing?”, “why did page count change?”, and “is this object using in-row, row-overflow, or LOB storage?”

01

Explain pages, extents, allocation units, files, and filegroups as distinct layers.

02

Describe PFS, GAM, SGAM, and IAM responsibilities without treating their bitmaps as application APIs.

03

Use supported catalog/DMV evidence before reaching for unsupported internals.

04

Recognize mixed-versus-uniform extent behavior as version/configuration history, not a universal tuning rule.

05

Build and safely remove a disposable storage probe.

Chapter continuity

Chapter 07 made concurrency visible. Chapter 08 moves one layer down: the same rows, locks, and log records eventually map to pages, allocation units, B+ trees, and log blocks. Mandatory labs use only free SQL Server 2025 Developer/Express and disposable lab08 objects inside ServiceHubLab.

1. From a logical row to pages and extents

A page is SQL Server's fundamental database storage unit for most rowstore data. A data page is 8 KiB and begins with a 96-byte header that identifies the page and carries engine metadata. A single row normally cannot consume the whole 8 KiB: the row format and slot array consume space, and variable-length data can move to ROW_OVERFLOW_DATA or LOB_DATA allocation units. An extent groups eight physically contiguous pages, so an extent is 64 KiB.

Do not confuse these layers with files. A data file contains many extents; a filegroup is a logical container for one or more data files; a partition of a heap or B+ tree owns allocation units; and an allocation unit owns pages/extents of a particular storage kind. Those distinctions explain why “table size,” “file size,” and “allocated page count” answer different questions.

sql · baseline instance, file, and partition evidence
USE ServiceHubLab;GOSELECT SERVERPROPERTY('ProductVersion') AS engine_build,       SERVERPROPERTY('Edition') AS edition;SELECT compatibility_level,recovery_model_descFROM sys.databases WHERE name=DB_NAME();SELECT file_id,name,type_desc,physical_name,size*8.0/1024 AS size_mb,       growth,is_percent_growthFROM sys.database_filesORDER BY file_id;SELECT fg.data_space_id,fg.name AS filegroup_name,fg.is_defaultFROM sys.filegroups AS fgORDER BY fg.data_space_id;GO

2. PFS, GAM, SGAM, and IAM answer different allocation questions

Page Free Space (PFS) pages track page-allocation state and approximate free-space categories. The Global Allocation Map (GAM) tracks extents that are free versus allocated. The Shared Global Allocation Map (SGAM) identifies mixed extents that still have a free page. An Index Allocation Map (IAM) belongs to an allocation unit and maps the extents that allocation unit uses across a GAM interval. These are engine-maintained system pages, not tables you update.

Mixed extents are historical context, not a reason to turn on old trace flags. Starting with SQL Server 2016, user databases default to uniform-extent allocation because MIXED_PAGE_ALLOCATION defaults to OFF; older advice centered on trace flag 1118 is therefore not a current SQL Server 2025 baseline. System-database history differs, so always inspect the target database rather than copying folklore.

sql · inspect the mixed-page allocation setting and object footprint
SELECT name,is_mixed_page_allocation_onFROM sys.databasesWHERE name=DB_NAME();GOIF SCHEMA_ID(N'lab08') IS NULL EXEC(N'CREATE SCHEMA lab08 AUTHORIZATION dbo;');DROP TABLE IF EXISTS lab08.PageProbe;CREATE TABLE lab08.PageProbe(    probe_id int IDENTITY(1,1) NOT NULL        CONSTRAINT PK_PageProbe PRIMARY KEY,    category char(1) NOT NULL,    payload varchar(700) NOT NULL);;WITH n AS(  SELECT TOP (3000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n  FROM sys.all_objects AS a CROSS JOIN sys.all_objects AS b)INSERT lab08.PageProbe(category,payload)SELECT CHAR(65 + n % 4),REPLICATE('x',650) FROM n;GOSELECT p.index_id,p.rows,au.type_desc,       au.total_pages,au.used_pages,au.data_pagesFROM sys.partitions AS pJOIN sys.allocation_units AS au ON au.container_id=p.hobt_idWHERE p.object_id=OBJECT_ID(N'lab08.PageProbe')ORDER BY p.index_id,au.type_desc;GO

3. Supported operational evidence first

sys.dm_db_index_physical_stats is documented and can report page count, page density, fragmentation, allocation-unit type, and B+ tree depth. sys.dm_db_page_info is also documented for SQL Server 2019+ and returns page-header metadata when you already know the file/page identifier. These are appropriate building blocks for repeatable operational tooling, subject to their permission and scanning-cost requirements.

sql · documented physical statistics
DECLARE @obj int=OBJECT_ID(N'lab08.PageProbe');SELECT index_id,index_type_desc,alloc_unit_type_desc,       index_level,page_count,avg_page_space_used_in_percent,       avg_fragmentation_in_percent,record_countFROM sys.dm_db_index_physical_stats(DB_ID(),@obj,NULL,NULL,'DETAILED')ORDER BY index_id,index_level DESC,alloc_unit_type_desc;GO

The exact page count and density depend on row format, engine build, compression, and prior modifications, so the lesson does not prescribe one expected numeric result. The expected shape is stable: the clustered primary key appears as a B+ tree and its leaf level is index level 0.

4. Low-level discovery has a supportability boundary

Microsoft's current page/extent guide explicitly marks sys.dm_db_database_page_allocations and sys.system_internals_allocation_units as unsupported. They can be valuable in a disposable learning lab, but they must not become a production monitoring contract. If you use the unsupported page-allocation function to discover one page, immediately switch back to the supported sys.dm_db_page_info for the page header and label the dependency.

sql · optional educational page discovery — unsupported input, supported header read
-- EDUCATIONAL ONLY: sys.dm_db_database_page_allocations is unsupported.DECLARE @file_id int,@page_id bigint;SELECT TOP (1)       @file_id=allocated_page_file_id,       @page_id=allocated_page_page_idFROM sys.dm_db_database_page_allocations     (DB_ID(),OBJECT_ID(N'lab08.PageProbe'),1,NULL,'DETAILED')WHERE is_allocated=1 AND page_type=1;SELECT @file_id AS discovered_file_id,@page_id AS discovered_page_id;-- Supported SQL Server 2019+ page-header function:SELECT *FROM sys.dm_db_page_info(DB_ID(),@file_id,@page_id,'DETAILED');GO
Wrong approach

Do not build alerting, capacity forecasts, or deployment gates around unsupported internals merely because a lab query works on CU7. Compatibility is not guaranteed. Prefer supported metadata for normal operations, and isolate low-level internals to expert diagnostics where the risk is understood.

5. Production judgment and cleanup

Storage internals should answer an operational question, not invite random page inspection. For capacity, use file/filegroup and allocation-unit metadata. For index health, use documented physical/operational DMVs and workload evidence. For a specific latch/wait page, sys.dm_db_page_info can connect the page identifier to object metadata. Permissions matter: SQL Server 2022+ commonly requires VIEW DATABASE PERFORMANCE STATE for these database performance DMVs. No restart, paid edition, multi-node topology, or preview feature is required.

sql · cleanup for the page probe
USE ServiceHubLab;DROP TABLE IF EXISTS lab08.PageProbe;-- Keep schema lab08 for later Chapter 08 lessons.GO

Check your understanding

  1. What is the size of a SQL Server extent?
  2. What does PFS track?
  3. What does IAM map?
  4. Why is sys.dm_db_database_page_allocations not a production API?
  5. What is the supported page-header alternative in SQL Server 2019+?
Review the answers

Eight 8-KB pages, or 64 KB.

Page allocation state and free-space information, rather than which extents belong to one object.

The extents used by one allocation unit across GAM intervals/files.

Microsoft marks it unsupported and subject to change.

sys.dm_db_page_info when the file and page identifiers are known.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.