我正在学习Sql server中的分配单元,并了解了3种类型
行溢出数据。
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_NAME='TEST_ALLOCATION_UNITS')
DROP TABLE TEST_ALLOCATION_UNITS
CREATE TABLE TEST_ALLOCATION_UNITS(
TEST_ID INT IDENTITY(1,1)
,NAME VARCHAR(4000)
,NAME1 VARCHAR(5000)
)
GO
INSERT INTO TEST_ALLOCATION_UNITS (NAME,NAME1) VALUES ('APPLE','BANANA')
GO 500
我在其中插入了500条记录
不,我已经运行了代码,我得到了这样的结果
select s.type_desc before_alter from sys.allocation_units s
join sys.partitions p on p.partition_id=s.container_id
where p.object_id=object_id('test_allocation_units')
现在我改变了表并将每个列的大小减少到50个字节,然后再次运行上面的select语句
alter table test_allocation_units alter column name varchar(50)
alter table test_allocation_units alter column name1 varchar(50)
select s.type_desc from sys.allocation_units s
join sys.partitions p on p.partition_id=s.container_id
where p.object_id=object_id('test_allocation_units')
问题
根据我在更改表之前的理解,该表的列的组合大小大于8 Kb,因此分配类型是In_row_data和Row_overflow_data 。 但是在alter语句之后的 ,即每个列的大小减少到50个字节,那么分配单元仍然是In_row_data和Row_overflow_data
请解释。
提前致谢
场景2
我尝试使用空表并运行以下代码
IF EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'TEST_ALLOCATION_UNITS'
)
DROP TABLE TEST_ALLOCATION_UNITS
CREATE TABLE TEST_ALLOCATION_UNITS (
TEST_ID INT IDENTITY(1, 1)
,NAME VARCHAR(4000)
,NAME1 VARCHAR(5000)
)
GO
SELECT s.type_desc before_alter,s.total_pages,s.used_pages,s.data_pages
FROM sys.allocation_units s
JOIN sys.partitions p ON p.partition_id = s.container_id
WHERE p.object_id = object_id('test_allocation_units')
ALTER TABLE test_allocation_units
ALTER COLUMN NAME VARCHAR(50)
ALTER TABLE test_allocation_units
ALTER COLUMN name1 VARCHAR(50)
SELECT s.type_desc after_alter,s.total_pages,s.used_pages,s.data_pages
FROM sys.allocation_units s
JOIN sys.partitions p ON p.partition_id = s.container_id
WHERE p.object_id = object_id('test_allocation_units')
我没有在表格中插入任何记录,上图中的结果显示在图中
请注意为什么即使在更改列大小后,分配单元也没有改变?
答案 0 :(得分:1)
获取数据"重新分配"你必须运行这个命令:
ALTER TABLE TEST_ALLOCATION_UNITS REBUILD
REBUILD建议SQL Server在HEAP TABLE上重新分配数据页。
答案 1 :(得分:0)
回答你的问题
在更改或之后,row_overflow数据未转换为in_row数据 更新表格
,该表从未使用过row_overflow数据,因此在更改列类型时无需转换。
在查询中添加更多列:
select
s.type_desc
,s.total_pages
,s.used_pages
,s.data_pages
from
sys.allocation_units s
join sys.partitions p on p.partition_id=s.container_id
where
p.object_id=object_id('test_allocation_units')
您会看到只有IN_ROW_DATA
的页数非零,而ROW_OVERFLOW_DATA
有0页保留和使用。
无论如何,当你存储" banana" varchar(5000)
列中的值,每行只存储6个字节(加上一些开销)。因此,将此列类型更改为varchar(50)
并不会更改数据页中的任何实质内容。
如果列具有char(5000)
类型,然后更改为char(50)
,则表在磁盘上占用的页数会有所不同。当你存储" banana"在char(5000)
列中的值,该值右侧填充了4994个空格到列的声明长度,因此此处声明的列大小会立即产生影响。
同样,无论如何,这些空间将存储在行内。如果您尝试创建包含char(4000)
和char(5000)
列的表,则创建将失败,因为SQL Server中的最大行大小为8060字节。
要查看ROW_OVERFLOW_DATA
的非零值,您需要在表格的varchar
列中存储长字符串。例如:
INSERT INTO TEST_ALLOCATION_UNITS (NAME,NAME1) VALUES
(REPLICATE('APPLE', 800)
,REPLICATE('BANANA', 833))
GO 500
在这种情况下,我们尝试在name
中存储4000个字节,在name1
中存储4998个字节,总共8998个(加上一些额外的开销),超过最大8060个字节,所以该值被推离行。
我建议尝试使用短字符串和长字符串添加/删除几行,并检查视图输出的更改方式。这可以帮助您了解视图的结果。