Skip to content

Data Records

FixedVar Format

The standard row format for uncompressed pages. Fixed length columns are stored first at fixed offsets, followed by the variable length columns located via an offset array.

KeyNameDescription
00
Status Bits ARecord type and status flags - whether the record has a null bitmap, variable length columns, and versioning information
00
Status Bits BAdditional status flags - currently only whether the record is a ghost forwarded record
00
Column Count OffsetTwo byte offset to the Column Count, marking the end of the fixed length data
00
Column CountNumber of columns in the record
00
Null BitmapOne bit per column, set to 1 if the column value is null
00
Variable Length Column CountNumber of variable length columns stored in the record
00
Variable Length Column Offset ArrayTwo bytes per variable length column giving the offset where each value ends - each value starts where the previous one ended
00
Fixed Length ValueFixed length column values, stored in column order at fixed offsets
00
Variable Length ValueVariable length column values, located via the offset array
00
Forwarding StubLeft behind when a heap row is moved to another page. Contains the RID of the row's new location so non-clustered index pointers stay valid

CD Format

The CD (Compressed Data) format is used on pages with row or page compression. Instead of fixed offsets, a column descriptor encodes how each value is stored so no space is wasted.

KeyNameDescription
00
Record HeaderSingle byte identifying the record as CD format, with flags including whether the record has versioning information and a long data region
00
Column CountNumber of columns in the record
00
Column DescriptorFour bits per column describing how the value is stored - null, a short value of 0 to 8 bytes, a long value, or a page dictionary symbol
00
Short Data Cluster ArrayColumns are grouped into clusters of 30. One byte per cluster gives the combined size of its short values, so a value can be located without scanning every descriptor
00
Short Field ValueValues of 8 bytes or less, stored in column order in the short data region
00
Long Data HeaderSingle byte header for the long data region at the end of the record
00
Long Data Offset CountNumber of entries in the Long Data Offset Array
00
Long Data Offset ArrayTwo bytes per long value giving the offset where each value ends
00
Long Data Cluster ArrayCluster entries for the long data region, used to jump to the values for a cluster of columns
00
Long Field ValueValues longer than 8 bytes, stored in the long data region

Sparse Vector

Sparse column values are stored in a sparse vector - a structure at the end of the record that only stores the sparse columns that have a value.

KeyNameDescription
00
Complex HeaderTwo byte header identifying the complex column type - 5 is an in row sparse vector
00
Sparse Column CountNumber of sparse columns with a value stored in the vector
00
Sparse ColumnsArray of two byte column ids identifying which sparse columns are stored
00
Sparse Column OffsetsTwo bytes per column giving the offset where each value ends

LOB Pointers

When a value is stored off-row the data record holds a pointer structure in its place - a LOB pointer to the root of the value's LOB structure, or a row overflow pointer to a variable length value pushed off the page.

KeyNameDescription
00
Pointer TypeThe type of pointer - LOB pointer, LOB root, or row overflow
00
TimestampValue linking the pointer to its LOB data, used by DBCC CHECKTABLE for consistency checks
00
LevelLevel of the LOB structure the root points into
00
Update SeqUpdate sequence number
00
Overflow LevelLevel field of a row overflow pointer
00
Overflow LengthTotal length of the off-row value a row overflow pointer covers
00
RIDRow Identifier (File Id:Page Id:Slot Id) of the LOB record the pointer leads to
00
UnusedPadding / unused bytes

LOB Records

Off-row values are stored in LOB records on LOB (Text/Image) pages. Small values sit in a single record, while larger values form a tree - a root record linking to data records, with internal records added as levels when the value grows.

KeyNameDescription
00
Status Bits ARecord type and status flags
00
Status Bits BAdditional status flags
00
LengthLength of the record
00
Blob IdIdentifier shared by all the records that make up one LOB value - the in-row pointer carries the same id
00
Blob TypeWhat part of the LOB structure the record is - Data (the value or a chunk of it), Internal (a record of links - the root and any intermediate levels of a MAX type's tree), SmallRoot (a small value held in the root record itself), or LargeRoot (a root of links used by other LOB formats)
00
Max LinksMaximum number of child links the record can hold
00
Current LinksNumber of child links in use
00
LevelLevel of the record in the LOB tree
00
SizeSize of the data held in a SmallRoot record
00
DataThe LOB value bytes - the whole value in a SmallRoot, or one chunk in a Data record
00
Child OffsetPer child link, the cumulative offset into the value the link covers up to - a byte position can be found by picking the right link
00
Child LengthLength covered by a child link
00
RIDRow Identifier of the child record a link points to