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.
| Key | Name | Description |
|---|---|---|
00 | Status Bits A | Record type and status flags - whether the record has a null bitmap, variable length columns, and versioning information |
00 | Status Bits B | Additional status flags - currently only whether the record is a ghost forwarded record |
00 | Column Count Offset | Two byte offset to the Column Count, marking the end of the fixed length data |
00 | Column Count | Number of columns in the record |
00 | Null Bitmap | One bit per column, set to 1 if the column value is null |
00 | Variable Length Column Count | Number of variable length columns stored in the record |
00 | Variable Length Column Offset Array | Two bytes per variable length column giving the offset where each value ends - each value starts where the previous one ended |
00 | Fixed Length Value | Fixed length column values, stored in column order at fixed offsets |
00 | Variable Length Value | Variable length column values, located via the offset array |
00 | Forwarding Stub | Left 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.
| Key | Name | Description |
|---|---|---|
00 | Record Header | Single byte identifying the record as CD format, with flags including whether the record has versioning information and a long data region |
00 | Column Count | Number of columns in the record |
00 | Column Descriptor | Four 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 Array | Columns 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 Value | Values of 8 bytes or less, stored in column order in the short data region |
00 | Long Data Header | Single byte header for the long data region at the end of the record |
00 | Long Data Offset Count | Number of entries in the Long Data Offset Array |
00 | Long Data Offset Array | Two bytes per long value giving the offset where each value ends |
00 | Long Data Cluster Array | Cluster entries for the long data region, used to jump to the values for a cluster of columns |
00 | Long Field Value | Values 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.
| Key | Name | Description |
|---|---|---|
00 | Complex Header | Two byte header identifying the complex column type - 5 is an in row sparse vector |
00 | Sparse Column Count | Number of sparse columns with a value stored in the vector |
00 | Sparse Columns | Array of two byte column ids identifying which sparse columns are stored |
00 | Sparse Column Offsets | Two 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.
| Key | Name | Description |
|---|---|---|
00 | Pointer Type | The type of pointer - LOB pointer, LOB root, or row overflow |
00 | Timestamp | Value linking the pointer to its LOB data, used by DBCC CHECKTABLE for consistency checks |
00 | Level | Level of the LOB structure the root points into |
00 | Update Seq | Update sequence number |
00 | Overflow Level | Level field of a row overflow pointer |
00 | Overflow Length | Total length of the off-row value a row overflow pointer covers |
00 | RID | Row Identifier (File Id:Page Id:Slot Id) of the LOB record the pointer leads to |
00 | Unused | Padding / 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.
| Key | Name | Description |
|---|---|---|
00 | Status Bits A | Record type and status flags |
00 | Status Bits B | Additional status flags |
00 | Length | Length of the record |
00 | Blob Id | Identifier shared by all the records that make up one LOB value - the in-row pointer carries the same id |
00 | Blob Type | What 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 Links | Maximum number of child links the record can hold |
00 | Current Links | Number of child links in use |
00 | Level | Level of the record in the LOB tree |
00 | Size | Size of the data held in a SmallRoot record |
00 | Data | The LOB value bytes - the whole value in a SmallRoot, or one chunk in a Data record |
00 | Child Offset | Per 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 Length | Length covered by a child link |
00 | RID | Row Identifier of the child record a link points to |