页面拆分是否会影响索引或表中的数据的物理排序?示例:如果您有一个索引的电子邮件列,并且页面拆分发生了很多,那么所列出的电子邮件是否会在列表中出现故障,现在更长时间了?
页面拆分/碎片如何与删除主键记录一起使用?示例:如果您有下表,主键是数字。
1, bob, chair
2, joe, table
3, brandon, lamp
4, jared, tv
让我们说你删除记录3.现在表读取1,2,4(乱序),然后记录3在以后重新插入?然后它将读1,2,4,3。记录4是否占用记录3的空间,或者是否在以后重新插入记录3的情况下保留?或者您是否必须执行索引重建以对其进行物理重新排序?
谢谢
答案 0 :(得分:0)
SQL Server使用聚簇索引表(默认情况下)。这些表按主键排序。
插入中间值时,页面会重新排列,以便为新行分配空间。据我了解,当你删除一行后,空间将被回收(在某些时候)。这些操作执行起来很昂贵。
这就是为什么通常建议使用主键的自动递增值,以避免您提到的问题。
答案 1 :(得分:0)
1。)聚簇索引是一个非物理的逻辑顺序,避免试图将其视为一个真实的物理顺序,索引和存储之间有太多的抽象层次来考虑物理顺序。 (范围分配,文件组,磁盘/ Lun上的碎片,Lun'它们本身 - 所有这些都使得物理订单的概念不正确。)
以维护逻辑顺序的方式处理页面拆分,更新表格的正向/反向双链表链接页面,以便将新页面插入到'顺序'可以这么说。
2。)物理顺序与逻辑 - 再次,只是停止考虑物理排序,即使行在同一页面上,页面的插槽数组也是维护页面本身数据实际顺序的数组。因此,在页面上它可能最终为1,2,4,3,插槽阵列将为4,3,2,1(插槽阵列从页面末尾开始并向后读取) - 是否空间重新开始 - 使用与否并不重要,因为它将处理页面上的偏移位置与通过该阵列维护的顺序。
Impaler提到使用主键的自动增量值 - 主键和群集键不必是同一个东西,而我同意您经常使用身份字段作为群集密钥 - 主要密钥密钥应根据需要和可用的候选密钥单独考虑。
SQL Server如何在存储级别工作可能会涉及一个非常复杂的主题,我个人会推荐Kalen Delaney的书,尽管其他人都可以使用。
答案 2 :(得分:0)
让我们来看看你的例子,看看会发生什么。
首先,虚拟表和虚拟数据。
CREATE TABLE testing (ID INT PRIMARY KEY, junk VARCHAR(100))
GO
INSERT INTO testing(ID, junk)
VALUES
(1, 'blah'),
(2, 'blahhhh'),
(3, 'Blabbb')
GO
现在,让我们看看存储它的实际数据页。
SELECT
*,
sys.fn_PhysLocFormatter(%%physloc%%) AS Page_Location
from testing
获取该函数的输出并将其放入DBCC PAGE
DBCC TRACEON(3604) --Send output of DBCC PAGE to SSMS Client
GO
DBCC PAGE('your_db_name',the_first_num_from_page_location,the_second_num_from_page_location,3)
这将显示数据页面实际上具有的内容。 “Slots”是表格中的行,页面从Slot 0开始。
Slot 0 Offset 0x60 Length 19
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 19
Memory Dump @0x0000004493BFA060
0000000000000000: 30000800 01000000 02000001 00130062 6c6168 0..............blah
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4
ID = 1
Slot 0 Column 2 Offset 0xf Length 4 Length (physical) 4
junk = blah
Slot 0 Offset 0x0 Length 0 Length (physical) 0
KeyHashValue = (8194443284a0)
继续阅读页面,您将看到3行数据。现在,删除记录2并重新运行page_location查询并在页面上查看。插槽1现在应该是您的ID = 3记录。
DELETE FROM testing
WHERE ID = 2
现在,重建您的PK索引并重新插入记录2.
ALTER INDEX your_pk here ON testing
REBUILD
INSERT INTO testing(ID, Junk)
VALUES
(2,'blerg')
GO
重新运行page_location查询,因为重建后页面可能已更改并查看您的插槽。即使您在3之后插入2,插槽1(第2行)也是您的ID = 2记录。
但是,数据页上有一个称为Slot Array的东西,它存储了数据的逻辑顺序。因此,即使页面上的数据可能完全无序地物理存储,插槽阵列也会告诉sql server如何根据索引对其进行逻辑排序。
你可以在这里看到这个:
DBCC TRACEON(3604) --Send output of DBCC PAGE to SSMS Client
GO
DBCC PAGE('your_db_name',the_first_num_from_page_location,the_second_num_from_page_location,2)
在最底部,您将看到偏移表: OFFSET表:
Row - Offset
2 (0x2) - 115 (0x73)
1 (0x1) - 136 (0x88)
0 (0x0) - 96 (0x60)
再次重建PK,看看它是如何变化的:
OFFSET TABLE:
Row - Offset
2 (0x2) - 135 (0x87)
1 (0x1) - 115 (0x73)
0 (0x0) - 96 (0x60)
因此,页面上的数据可能完全是物理上的乱序,但是插槽数组会根据您的索引定义告诉引擎它应该处于哪个顺序。您在SSMS或数据页面上的结果可能看起来是按物理排序的顺序,但实际上它可能完全不同,并且插槽阵列正在跟踪它应该处于什么顺序。重新插入PK行无序可能肯定会导致页面拆分,如果它必须推送数据。