use*_*729 4 sql-server sql-server-2019
我试图了解 SQL Server 在将记录插入堆表时的行为。根据关于 sql Server博客文章,第 2 段“如果其大小超过页面大小的 20%(8,060 字节 * 0.2 = 1,612 字节),SQL Server 将不会将新行放入页面。 ”
如果我正确理解了该语句,那么如果该表有一个大小为 2025 字节的记录,则第二条记录应该放在另一页上。但是,我的测试并不同意
设置脚本
环境:SQL 2019 x64 开发版。
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));
Run Code Online (Sandbox Code Playgroud)
并运行以下代码
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]
Run Code Online (Sandbox Code Playgroud)
上面的 SELECT 返回如下结果,与 20% page size 的说法不一致。
我尝试在插入后查看 DBCC PAGE 结果,但 DBCC PAGE 结果没有与插入记录的大小相加。
设置脚本
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
);
Run Code Online (Sandbox Code Playgroud)
记录大小仅为数据页的 25%,但 PFS 显示 50% 已满,为什么?
发出第二张插页并查看 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
);
Run Code Online (Sandbox Code Playgroud)
小智 6
让写这篇博文的人澄清一下:)
你的报价有点断章取义。全文如下:
例如,如果数据页存储 4,100 字节的数据,因此有 3,960 字节的可用空间,PFS 将指示该页已满 51-80%。如果新行的大小超过页面大小的 20%(8,060 字节 * 0.2 = 1,612 字节),则 SQL Server 不会将新行放入页面。
基本上,这意味着如果页面上有80_PCT_FULL标志,SQL Server 会期望该页面最多填充 80% 并且只有 1,612 字节可用。
您的测试证实:
希望这能澄清情况。
归档时间: |
|
查看次数: |
107 次 |
最近记录: |