I am trying to understand the behaviour of SQL Server when it INSERT record into a Heap table. According to about sql Server blog post, paragraph 2 "SQL Server would not put a new row to the page if its size exceeds 20 percent (8,060 bytes * 0.2 = 1,612 bytes) of the page size."
If I understand the statement correctly then if the table had a record of size 2025 byte the second record should go on another page. However, my test is not agreeing with that
SETUP SCRIPT
Environment: SQL 2019 x64 Developer edition.
create table dbo.Heap(id INT, Val varchar(8000) not null);
GO
insert into dbo.heap(ID, val) values (1,replicate('*',2010));
insert into dbo.heap(ID, val) values (2,replicate('*',2010));
insert into dbo.heap(ID, val) values (3,REPLICATE('*',2010));
insert into dbo.heap(ID, val) values (4,REPLICATE('*',2010));
And run following code
SELECT PARSENAME(REPLACE(REPLACE(REPLACE(CAST(sys.fn_PhysLocFormatter (%%physloc%%) AS varchar),')',''),'(',''),':','.'),2)PageNo,
sys.fn_PhysLocFormatter (%%physloc%%) AS [Location],* FROM heap ORDER BY [ID]
The above SELECT returns the following result, which doesn't agree with 20% page size statement.
I tried reviewing the DBCC PAGE result after insert but the DBCC PAGE result doesn't add up the size of the inserted record.
SETUP Script
DROP TABLE IF EXISTS heap
go
create table dbo.Heap(id INT, Val varchar(8000) not null);
GO
insert into dbo.heap(ID, val) values (1,replicate('*',2010));
go
dbcc traceon(3604);
dbcc page
(
'demodb' -- Database name
,1 -- File ID
,416 -- Page ID
,1 -- Output mode: 3 - display page header and row details
);
The records size was only 25% of the data page however PFS shows 50% full why?
Issue the second insert and review the PAGE
insert into dbo.heap(ID, val) values (2,replicate('*',2010));
dbcc page
(
'demodb' -- Database name
,1 -- File ID
,416 -- Page ID
,1 -- Output mode: 3 - display page header and row details
);
Best Answer
Let the person who wrote this blog post clarify :)
Your quote is a bit out of context. The full paragraph is:
Basically, it means that if you have 80_PCT_FULL flag on the page, SQL Server would expect that page may be up to 80 percent populated and have only 1,612 bytes available.
Your tests confirmed that:
Hope this clarifies the situation.