使用页面压缩时的行开销是多少?


10

我创建了一个包含650 Numeric(19,4)列的表。当我打开页面压缩时,通过运行

ALTER TABLE fct.MyTable REBUILD  WITH (DATA_COMPRESSION = PAGE);

我懂了

消息1975,级别16,状态1
索引“ PK_Mytable”的行长度超过了“ 8060”字节的最大允许长度。

但是650乘以9字节仅是5850字节,与规定的8060字节的限制相去甚远。

服务器正在运行Windows 2012 r2和SQL Server 2016 SP1 CU2

使用页面压缩时的行开销是多少?

这是一些代码来显示我的意思:

/* test script to demo MSG 1975 */
DECLARE @sql NVARCHAR(max)='', @i INT =0
drop table if exists dbo.mytable;

SET @sql = 'Create table dbo.Mytable (MyTableID bigint not null 
  identity(1,1) primary key clustered, '

WHILE @i < 593 BEGIN
    SET @sql += ' Column' + LTRIM(@i) + ' numeric(19,4) null, '
    SET @i +=1
END

SET @sql += ' LastColumn int) '
--SET @sql += ' with (DATA_COMPRESSION = ROW) '
SET @sql += ' with (DATA_COMPRESSION = PAGE) '

SELECT @sql
EXEC sys.sp_executesql @sql

SELECT top 10000 * FROM dbo.MyTable MT

行压缩也失败,但是行计数不同。


您的主键有多大?如果这是事实表,并且您想压缩和增强性能,则建议您阅读列存储索引,它们会产生很大的影响。页面压缩的开销是要解压缩更多的cpu用法。
Stijn Wynants

@StijnWynants; BigInts使用8个字节。这确实是事实,但是没有足够的行来保证列存储索引。
Henrik Staun Poulsen

Answers:


13

如果您尝试在没有聚集的PK约束的情况下创建表,则将得到一个略有不同的错误:

消息1701,级别16,状态1,行1创建或更改表'Mytable'失败,因为最小行大小为8067,包括1530字节的内部开销。这超过了8060字节的最大允许表行大小。

在此错误信息中,您可以看到页面压缩有1530字节的内部开销。

现在,您可以进行数学计算:

  • bigintMyTableID的8个字节
  • intLastColumn 为4个字节
  • 593 numeric(19,4)列中的每列9个字节(总计5337个字节)
  • 1530字节的压缩开销

因此,8 + 4 +(593 * 9)+ 1530 =6879。请 稍等.... 仍低于8060。怎么了?!


页面压缩算法实际上将几种压缩算法堆叠在一起。第一步是应用ROW压缩。该错误消息中列出的1530字节的开销中不包括行压缩的开销。

您可以在我的博客BOL 阅读有关行压缩如何工作的更多信息。您会在BOL文章中注意到,它将该numeric存储描述为“此存储与vardecimal存储格式完全相同”,但没有说明vardecimal这篇文章涵盖vardecimal了更多内容-本质上讲,它每列增加2个字节的开销来存储实际长度(类似于此varchar操作)。

行压缩将为593 numeric列中的每列增加2个字节,再加上bigintint将需要1个字节的开销。

行压缩存储的要求是:

  • bigintMyTableID的8个字节+ 1个字节的开销
  • intLastColumn有4个字节+ 1个字节的开销
  • 593 numeric(19,4)列的每列9字节+ 2字节开销
  • 1188字节的ROW压缩开销

8 + 4 +(593 * 9)= 5349字节数据

1 + 1 +(593 * 2)= 1188字节的行压缩开销

行压缩模式总共6537字节


现在我们有了行压缩模式的行大小,可以重新查看数学了。页面压缩的行大小将是数据大小+行压缩开销+页面压缩开销:

  • bigintMyTableID的8个字节
  • intLastColumn 为4个字节
  • 593 numeric(19,4)列各9个字节
  • 1188字节的ROW压缩开销
  • 1530字节的PAGE压缩开销
  5349字节数据 
+ 1188字节的行压缩开销 
+ 1530字节页面压缩开销 

总计8067字节


1
我喜欢您的结论:“在大多数情况下,您会发现行压缩能够节省一些空间,但并非总是如此。” 2718字节的开销比我预期的要大得多。非常感谢您抽出宝贵的时间写出如此详细的答案。
Henrik Staun Poulsen

1
@HenrikStaunPoulsen需要记住的另一件重要事情是,SQL Server需要假设您的数据可能无法压缩。因此,即使您的数据压缩到少于8060字节,SQL Server也必须基于理论上最大行大小来计算不可压缩数据的行大小。
AMtwo

3天后,我仍然对行压缩所需的字节数感到惊讶;每列2个字节。页面压缩在此之上几乎增加了3个字节。但; 感谢您的帮助。这是最有用的。
Henrik Staun Poulsen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.