In our last post, we have gone through the data page structure and we have noticed that there is an overhead of 7 bytes in each records. Let us try to understand how SQL Server stores the records in a data pages.
Data record stores actual data. In other words, it store the records in heap or the records in the leaf level of clustered index. The data records are stored in a structure which helps SQL server manage these record efficiently. Let us see a pictorial representation of a data record.
The section which are marked in blue are part of all data records.The other section will be part of the data record depends on fixed length / variable length column are available in the table structure.
The first one byte is used for status Bits 1 which define the properties of the record :
Bit 0 : Versioning information. In SQL server 2008 this is always 0
Bits 1 to 3: This is three bit value define the record type.
0 data record.
1 Forwarded record.
2 a forwarding stub.
3 Index record.
4 blob fragment or row overflow data.
5 ghost index record.
6 ghost data record
7 ghost version record
Bit 4: Null bitmap exists or not.In SQL server 2008 null bitmap exists even if there is no null able columns
Bit 5: Indicate variable column exists or not.
Bit 6 :Indicate that row contain versioning information
Bit 7 : Not used in SQL server
The second byte used for status bits 2 . Only one bit is used in this to indicate that the record is ghost forwarded record.
The next 2 bytes are used to store the length of fixed portion of the record.This include the two status bytes,2 bytes used for this field and actual size of fixed length data in the table. For example if a table does not have any fixed length column the value in this field will be 4.This is the same value will be displayed in the
pminlen field in the page header. (Refer the Page Structure
post)
The next n bytes are used to store the fixed length data available in the table where n is the total size of the fixed length column in the table. This part will not be there in the record structure if all column in the table are variable length column.
Next 2 bytes are used to store the total number of column in the table.
Next n bytes are used for null bitmap. one bit for each column in the table. value 1 in each bit indicate the corresponding column has NULL value in that record. The value of n will be no.column the table/8 and round to next integer value.
Next 2 bytes are used to store the number of variable length column in the table.
Next n bytes are used to store variable column offset array .This is nothing but the starting offset value (with respect to the page) of each variable length column.Each variable column requires 2 bytes. The value of n will be 2 X no. of variable length column in the table.
Next n bytes are used to store the actual data of variable length column . The value of n will be the total size (actual data stored not in the definition of the table) of variable length column.
Let us see the same example that we considered in the page structure
post
CREATE TABLE Customer (
FirstName CHAR(200),
LastName CHAR(300),
Email CHAR(200),
DOB DATE, --Size is 3
)
GO
INSERT INTO Customer VALUES('William','James','William.J@yahoo.com','1982-01-20')
INSERT INTO Customer VALUES('Jade','Victor','Jade.V@yahoo.com','1985-08-12')
INSERT INTO Customer VALUES('Jonas','hector','Jonas.h@yahoo.com','1980-10-02')
INSERT INTO Customer VALUES('William1','James','William.J@yahoo.com','1982-01-20')
INSERT INTO Customer VALUES('Jade1','Victor','Jade.V@yahoo.com','1985-08-12')
INSERT INTO Customer VALUES('Jonas1','hector','Jonas.h@yahoo.com','1980-10-02')
INSERT INTO Customer VALUES('William2','James','William.J@yahoo.com','1982-01-20')
INSERT INTO Customer VALUES('Jade2','Victor','Jade.V@yahoo.com','1985-08-12')
INSERT INTO Customer VALUES('Jonas2','hector','Jonas.h@yahoo.com','1980-10-02')
INSERT INTO Customer VALUES('William3','James','William.J@yahoo.com','1982-01-20')
GO
DBCC IND('mydb','customer',-1)
This gives me page number 148 with page type 1
DBCC TRACEON(3604)
GO
DBCC page('mydb',1,148,3)
The output will look like the image given below:
The pminlen value 707 in the header is the total size of the column (703 bytes) , 2 bytes used for status bytes and 2 bytes used to store the size of fixed length columns. The Length 710 mention in the record slot is the sum of pminlen, size of null bitmap (1 byte) and 2 bytes used to store the number column in the table.
Let us try another example with variable length column.
USE MyDb