Cai*_*haw 7 sql-server bcp compression sql-server-2016
我有很多大表(大约 1000 万行宽)需要定期加载到 SQL Server 2016 中以进行只读报告。我希望这些表在磁盘上尽可能小,这比加载或查询的性能改进更重要。
这是我对不需要进一步索引的表所做的工作:
DATA_COMPRESSION=PAGE. 表中的列类型是 varchar(不超过 512,不是最大值)、float、tinyint 或日期(不是日期时间)。所有列都创建为可为空的,并且没有定义主键或外键——它们与查询无关,表永远不会直接更新。一切的默认排序规则是SQL_Latin1_General_CP1_CI_AS.
当我这样做时,我可以看到sys.allocation_units该页面数据压缩已应用于堆,并且我可以看到sys.partitions填充因子正确为 0 (100%)。由于表比未压缩的表小得多,我认为压缩已完成。
但是,如果我然后使用相同的选项重建DATA_COMPRESSION=PAGE,则假定已经压缩的表会缩小大约 30%!看起来它从每个数据页大约 17 行到每页 25 行。(虽然只有一次。在那之后再次重建不会使它比第一次重建更小。)
问题
所以我的问题是:(a)这里发生了什么?(b) 有没有办法在加载表时直接获得这个超小的压缩大小,而无需在加载数据后重建?
@HandyD是完全正确的,我只想强调一些其他方法来在插入堆时进行压缩。
来自同一个文件
当堆配置为页面级压缩时,页面仅通过以下方式接收页面级压缩:
- 在启用批量优化的情况下批量导入数据。
- 数据是使用 INSERT INTO ... WITH (TABLOCK) 语法插入的,并且表没有非聚集索引。
- 通过执行带有 PAGE 压缩选项的 ALTER TABLE ... REBUILD 语句重建表。
据此,您可以利用最少记录的批量插入或使用INSERT INTO ... WITH (TABLOCK) 来获得PAGE压缩,而无需进行重建。
(a) 这里发生了什么?(b) 有没有办法在加载表时直接获得这个超小的压缩大小,而无需在加载数据后重建?
PAGE插入堆时有获得压缩的规则,添加-h "TABLOCK"到您的bcp命令中以获得压缩。
ROW压缩无需这些先决条件即可工作,并且是以下示例中使用的最少压缩量,感谢@DenisRubashkin指出这一点!
示例启动数据和 BCP 输出命令
--Tested on SQL Server 2014 SP2
CREATE TABLE dbo.CompressedHeap_Source( Val varchar(512),
Datefield Date,
Tinyfield TinyINT,
Floatfield float)
WITH (DATA_COMPRESSION = PAGE);
INSERT INTO dbo.CompressedHeap_Source
(
Val,Datefield,Tinyfield,Floatfield)
SELECT 'Bla',cast(getdate() as date),1,1.2412
FROM master..spt_values spt1
CROSS APPLY master..spt_values spt2;
--bcp TEST.dbo.CompressedHeap_Source out E:\Data\HeapData.bcp -c -T
Run Code Online (Sandbox Code Playgroud)
在ROW压缩和非压缩尺寸
132272 KB对堆进行标准插入时的数据大小为 ROW压缩但未PAGE压缩。
176216 KB对于我们的测试,没有任何压缩的数据大小是〜。
exec sp_spaceused 'dbo.CompressedHeap_Source'
name rows reserved data index_size unused
CompressedHeap_Source 6365530 132296 KB 132272 KB 8 KB 16 KB
Run Code Online (Sandbox Code Playgroud)
插入 ... 使用 TABLOCK
插入WITH TABLOCK为我们提供了PAGE压缩数据大小,69480 KB.
INSERT INTO dbo.CompressedHeap_Source2 WITH(TABLOCK)
(
Val,Datefield,Tinyfield,Floatfield)
SELECT 'Bla',cast(getdate() as date),1,1.2412
FROM master..spt_values spt1
CROSS APPLY master..spt_values spt2
Run Code Online (Sandbox Code Playgroud)
批量插入
现在,当我们创建一个也被page压缩的目标堆表并执行批量插入时with tablock:
CREATE TABLE dbo.CompressedHeap_Destination( Val varchar(512),
Datefield Date,
Tinyfield TinyINT,
Floatfield float)
WITH (DATA_COMPRESSION = PAGE);
bulk insert dbo.CompressedHeap_Destination
from 'E:\Data\HeapData.bcp' with (TABLOCK)
Run Code Online (Sandbox Code Playgroud)
数据被page压缩并且也在69480 KB:
name rows reserved data index_size unused
CompressedHeap_Destination 6365530 69512 KB 69480 KB 8 KB 24 KB
Run Code Online (Sandbox Code Playgroud)
BCP 输入与 TABLOCK
与提示一起BULK INSERT WITH TABLOCK使用可以获得与 相同的结果。这是有道理的,他们在内部做同样的事情BCP IN-h "TABLOCK"
--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T -h "TABLOCK"
Run Code Online (Sandbox Code Playgroud)
结果大小为 69480 KB
BCP 输入,无 TABLOCK
使用 BCP 从目标表的副本中的同一文件加载数据
标准 bcp 命令会生成非压缩数据:
--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T
Run Code Online (Sandbox Code Playgroud)
数据大小为132272 KB(行压缩)。