考虑一个总是单调增加的值的 B 树索引,例如 IDENTITY 类型的列。使用传统的 B 树实现,每当节点已满时,它将被拆分 50%/50%,我们最终得到一个 B 树,其中(几乎)所有节点都只有 50% 已满。
我知道 Oracle 会发现值何时不断增加,在这些情况下,Oracle 会执行 90%/10% 的拆分。这样,(几乎)所有节点都将充满 90%,并且对于这些非常常见的情况,可以获得更好的页面利用率。
我无法在 SQL Server 中找到类似功能的文档。但是,我进行了两次实验,分别在索引中插入了 N 个随机整数和 N 个连续整数。前一种情况使用了更多的页面,后者。
SQL Server 是否提供类似的功能?如果是这样:你能指点我一些关于这个功能的文档吗?
更新: 通过下面提供的实验,似乎叶节点保持未分裂,内部节点分裂 50%/50%。这使得增加键上的 B 树比随机键上的更紧凑。然而,Oracle 的 90%/10% 方法甚至更好,我仍然在寻找一些官方文档来验证实验中看到的行为。
我对 MS SQL 中的页面拆分有点困惑,我正在寻找明确的答案。这个故事似乎有两个版本:
1 - Fillfactor 仅影响创建/重建索引时的完整页面。页面拆分始终为 50/50
2 - Fillfactor 也会影响页面的分割方式。因此,如果有 70% 的填充因子并且页面溢出,它将拆分 70/30
非常感谢
我在使用 Azure SQL Server PAAS 的实时环境中遇到了很多我不理解的页面拆分。正在发生的更新不应增加行的大小,因此永远不会导致页面拆分。此外,该行为仅发生在 Azure 中,不会发生在本地 SQL 实例上。
我使用的是使用 eDTU 定价和标准层 (200 eDTU) 的 Azure 弹性池。
我创建了以下示例来演示:
create table dbo.TestSplit
(
TestSplitId int not null identity,
MyInt int not null,
constraint PK_C_dbo_TestSplit_TestSplitId primary key clustered (TestSplitId)
);
Run Code Online (Sandbox Code Playgroud)
插入 100,000 行且 MyInt = 5:
insert into dbo.TestSplit
(MyInt)
select top(100000) 5
from sys.columns AS a
cross join sys.columns AS b
cross join sys.columns AS c
Run Code Online (Sandbox Code Playgroud)
运行以下 SQL 显示已创建 384 个页面,并且有 2 个碎片。
select
ix.name as index_name,
st.index_type_desc,
st.fragment_count,
st.page_count …
Run Code Online (Sandbox Code Playgroud) azure-sql-database page-splits accelerated-database-recovery
我试图了解 SQL Server 中的页面拆分,阅读什么是页面拆分?发生什么了?为什么会这样?为什么要担心?通过托尼·罗杰森
CREATE TABLE mytest
(
something_to_see_in_data CHAR(5) NOT NULL CONSTRAINT pk_mytest PRIMARY KEY CLUSTERED,
filler VARCHAR(3000) NOT NULL
)
go
insert mytest ( something_to_see_in_data, filler ) values( '00001', replicate( 'A', 3000 ) )
insert mytest ( something_to_see_in_data, filler ) values( '00002', replicate( 'B', 1000 ) )
insert mytest ( something_to_see_in_data, filler ) values( '00003', replicate( 'C', 3000 ) )
go
Run Code Online (Sandbox Code Playgroud)
要检查我的表的页面:
DBCC IND ( 0, 'mytest', 1);
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE mytest …
Run Code Online (Sandbox Code Playgroud) 我们一直遇到一个表上的页面拆分问题,这是一个特别麻烦的问题 - 它是数据库中活动的审计日志,并且已经增长到 1TB 以上。主要索引位于记录类型上,它是 an NVARCHAR(100)
- 因为当有 5 种记录类型时您需要它 - 它比 aTINYINT
和记录 id更有意义- 它是 anNVARCHAR(200)
而不是记录的整数键。
它们还涵盖索引,包括键、旧值、新值等——非常广泛。
这是一个旧系统,不幸的是,这种审计的代码无处不在,而不是集中在一个程序中。它无法改变,我们正在经历漫长的微服务重写的痛苦过程。
因此,我将两个索引的填充因子从 100% 降低到 85%。
并且页面拆分变得更糟。我会说大约 3 倍的页面拆分。
这是一个普遍的结果吗?大多数建议说减少填充因子以提高页面拆分性能。我可以理解为什么它会这样做,因为键中数据的宽度。
建议是进一步降低填充因子,还是将其恢复原状?