I'm doing tests to better understand those minimal technical details about tables, pages, and etc.

I'm using sp_spaceused to better understand this with INT values ( I will do a lot of more tests with other datatypes, But I think the logic behind each datatype is the same).

OK. First I created a simple table with id int.

create table Aliens( id int)

Inserting only 1 value (Insert into table value (1)), I have this:

| name | rows | reserved | data | index_size | Unused |
| id   | 1    | 16 KB    | 8 KB | 8 KB       | 0 KB   |

OK. I can understand that we have here USED 8KB because this is the size of a page. correct? But why does SQL server reserves 16KB for this?

Then, I delete this row, and the result is the same:

| name | rows | reserved | data | index_size |
| id   | 1    | 16 KB    | 8 KB | 8 KB       |

This is because I didn't rebuild the table. After rebuilding the table:

| name | rows | reserved | data | index_size | unused |
| id   | 0    | 72 KB    | 8 KB | 8 KB       | 56 KB  |

Why now I have more reserved ( 72KB )? I deleted data and rebuilded. Now, is my table bigger? Is this because of log? and why is unused 56KB? 72-56 is 16. Is this because DATA and INDEX are separated? my table has no PK, nor indexes.

Now, when I insert 286 values ( all 1's, with go 286):

| name | rows | reserved | data  | index_size | unused |
| id   | 286  | 24 KB    | 16 KB | 8 KB       | 0 KB   |

Now I can see data = 16kb because There's so much information, that the SQL is now using 2 pages. But why index_size is still 8kb?

and How about NULL VALUES? according to This question here, null values on int field takes 4 bytes. a Char(10) takes 10 bytes. So, null values store the same amount as the datatype itself? Unless we are using sparse columns.

Thanks. any additional information would be appreciated.I think it's time to improve my knowledge with this details.

  • 2
    Can you show the table definition? Oct 18, 2018 at 15:02
  • If you're wanting to improve your knowledge, may I suggest you also improve your version of SQL Server? Newer versions have an undocumented dmv "dm_db_database_page_allocations" which helps you find out where/what the pages are.
    – Forrest
    Oct 18, 2018 at 15:13
  • Hey @Erik, it's just a Int ID table, and I'm inserting the value = 1. and @Forrest, I have here 3 version of sql servers ( 2008/2012 in production and I have 2014 for test purposes ). And good to know, I will implement these tests with this DMV on other versions too.
    – Racer SQL
    Oct 18, 2018 at 15:15

1 Answer 1


What you want to read up on is how SQL Server allocates pages (try this). Looking at data size in a row will take different tools.

Here's sample test code for a later version of SQL Server (I ran this on 2016)

USE [TestDB]

INSERT dbo.Aliens VALUES (1)

FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.Aliens'),NULL,NULL,'DETAILED')

EXEC sp_spaceused 'dbo.Aliens'

This shows an IAM page and a data page for the table, and bunch of blank pages. Why the blank pages? SQL Server reserves an entire extent for the table (because I'm using 2016 - earlier versions behave differently), expecting to use those blank pages for later inserts. In 2008r2, your table starts with a single page in a mixed extent, but the rebuild pushes it to a uniform extent.

Here's code to use if you want to look at rows

@file BIGINT,
@db INT = (SELECT DB_ID())

SELECT TOP 1 @pageid = allocated_page_page_id, @file = allocated_page_file_id
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.Aliens'),NULL,NULL,'DETAILED')
WHERE page_type = 1


DBCC PAGE(@db,@file,@pageid,3)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.