This article is looking deep into storage structures starting with the Heap table. This is something to become familiar with as part of the basics of SQL Server internals.
The following are terms to be familiar with before looking deep into storage structures.
1. Page: is 8kb in size. A page is divided into 3 parts, the Header, Records and an Offset Array. The Header is 96 bytes and contains meta information about a page, like page number, owning object and type of page. At the end of the page is an Offset Array of 36 bytes providing pointers to a location. Between these two areas are 8060 bytes where records are stored.
Header -> 96 bytes
Records -> 8090 bytes
Offset Array -> 36 bytes
2. Extent: contains 8 pages or 64 KB in size. is a collection of 8 pages. The group called is called an extent. It can be of 2 types, either mixed or Uniform Extent. A Mixed Extent is pages allocated to multiple objects. For example, if a table has less than eight pages then they are put into a Mixed Extent. All ages of Uniform Extents are allocated to a single object. We can say they are a contiguous allocation of pages.
3. Page Free Space (PFS): It keeps the information regarding free space in pages. There will be a PFS for every 8000 pages.
4. Global Allocation Map (GAM): It’s the third page in each data file. 1 GAM covers up to 4GB of data.
5. Shared Global Allocation Map (SGAM): It’s the fourth page in each data file. It keeps information related to Extents, whether it is Mixed or not. 1 SGAM covers up to 4 GB of data.
Let’s run the following code:
CREATE DATABASE IndexInternalsDeep
CREATE TABLE HeapTable
id INT IDENTITY(1,1),
INSERT INTO HeapTable VALUES(‘Vikrant More’)
INSERT INTO HeapTable VALUES(‘Suraj Sheikh’)
SELECT * FROM HeapTable
— Output from the above table like this
—- LOOKING FOR EXTENT INFORMATION.
Description of columns in EXTENTINFO:
• file_id and page_id: represents a file number where the pages reside and a page number within the file where the data lives.
• pg_alloc: Number of pages allocated from the extent to the object.
• ext_size: Size of the extents
• object_id: Object id for the table.
• index_id: Provides the id of the index; 0 for the heap, 1 for the clustered index and non-clustered ids >= 2.
• partition_number: Partition Number for the heap or index.
• iam_chain_type: Type of data stored (in row data, row overflow and so on)
• pfs_bytes: byte array that identifies the number of free space.
— LOOKING FOR INDEX INFORMATION
Description of columns in IND:
• PageFID and PagePID: represents a file number where pages reside and a page number within the file where data lives.
• IAMFID: Fileid of the file containing the page (refer to sysfiles).
• ObjectID: Objectid of the table used.
• IndexID: Provides the id of the index. 0 for heap, 1 for clustered index, non-clustered ids >= 2.
• PartitionNumber: it’s for the heap or index.
• PartitionID: it’s for the heap or index.
• iam_chain_type: Type of data stored (in row data, row overflow and so on).
• PageType: 1 refers to Data page, 2 -> Index page, 3 and 4 -> text pages.
• IndexLevel: 0 refers to leaf. The highest value refers to the root of an index.
• NextPageFID and PrevPageFID: refers to the next and previous file numbers.
• NextPagePID and PrevPagePID: refers to the next and previous page numbers.
Script to check space allocation details using the following query.
INNER JOIN sys.partitions p on obj.object_id = p.object_id
INNER JOIN sys.allocation_units AU on au.container_id = p.hobt_id
INNER JOIN sys.system_internals_allocation_units SIAU on SIAU.container_id =au.container_id
WHERE obj.object_id = object_id(‘Heaptable’)
identifying First Page ID based on First_page
First_page value = 0x420100000100.
A set of 2 Hexadecimal numbers represent a byte.
Read the following number from right to left (excluding the “0x” prefix):
0x 42 01 00 00 01 00
After reading it from right to left it should be:
0x 00 01 00 00 01 42
The preceding hexadecimal number is divided into 2 groups, the first group is 2 bytes and the second group is 4 bytes.
The first group, 00 01, represents the file group number.
second group, 00 00 01 42, represents the page number.
decimal equivalent of the first group, in other words 00 01, is 1 so the File Group ID = 1.
Now let’s convert 00 00 01 42 into the decimal equivalent,
following is the way to convert the hexadecimal number into decimal equivalent:
=> 1*16^2 +4*16^1 +2 * 16^0
=> 1 * 256 + 4 *16 + 2 * 1 (anything raise to 0 = 1)
=> 256 + 64 + 2
=> 322 — PagePID