如何查看 SQL Server 表中的数据是否经过页面压缩?

Cai*_*haw 10 sql-server compression sql-server-2016

这是我昨天提出的一个问题的后续问题:我可以批量插入空的页面压缩表并获得完全压缩吗?这个问题的答案(转述自 Randi Vertongen 的优秀回答)是肯定的,但它要求批量插入采用表级锁;否则,大容量插入采用行级锁并仅执行行数据压缩。这就提出了一个问题:之后我如何知道应用了什么压缩?

下面是在理论上页压缩的表中创建行压缩数据的步骤:
1. 创建一个表,DATA_COMPRESSION=PAGE并不使用sp_tableoption打开该表的“批量加载表锁定”选项。
2. 使用 bcp 将平面文件中的数据批量插入到新表中,但不指定-h TABLOCK锁定表的选项。

结果是一个表中的数据在行级别上被压缩(小于未压缩表但大于页压缩表),但检查sys.allocation_units目录表显示数据压缩为页。

问题

在这种情况下,当表的数据分配用于页面压缩时,我该怎么做才能确定该表中的数据是否经过页面压缩?

Sol*_*zky 15

要查看数据页当前是否确实被“PAGE”压缩,您可以使用未记录的 DMF sys.dm_db_database_page_allocations()。该is_page_compressed字段包含您要查找的信息。您将需要使用DETAILED模式(即第 5 个参数),否则该字段中的值都将是NULL.

要清楚(基于问题的措辞,“我该怎么做才能确定该表中的数据是否经过页面压缩?”),这不是一个全有或全无的问题:应用了页面压缩每个数据页,因此您可以没有压缩,全部被压缩,或两者之间的任何组合。因此,您需要查看所有页面。不,您不能一定假设单个非页面压缩页面表明您需要,REBUILD因为未填充页面不会压缩。

例如:

SELECT [is_page_compressed]
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED');
Run Code Online (Sandbox Code Playgroud)

下图显示了数据页最初不是页压缩的,而是REBUILD操作后的:

USE [tempdb];

-- DROP TABLE dbo.CompressedHeap;
CREATE TABLE dbo.CompressedHeap
(
  ID INT IDENTITY(1, 1) NOT NULL,
  String sysname,
  [MaxLength] SMALLINT,
  [Type] VARCHAR(5)
) WITH (DATA_COMPRESSION = PAGE);


INSERT INTO dbo.CompressedHeap ([String], [MaxLength], [Type])
  SELECT col.[name], col.[max_length], obj.[type]
  FROM   master.sys.columns col
  CROSS JOIN master.sys.objects obj;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 394 pages


ALTER TABLE dbo.CompressedHeap REBUILD;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 179 pages
Run Code Online (Sandbox Code Playgroud)