我可以批量插入一個空的頁面壓縮表並獲得完全壓縮嗎?
我有很多大表(大約 1000 萬行寬)需要定期載入到 SQL Server 2016 中以進行只讀報告。我希望這些表在磁碟上盡可能小,這比載入或查詢的性能改進更重要。
這是我為不需要進一步索引的表所做的:
- 用 . 創建表
DATA_COMPRESSION=PAGE
。- 使用 bcp 將平面文件中的數據批量插入到新表中。
表中的列類型是 varchar(從不超過 512,而不是最大值)、float、tinyint 或 date(不是 datetime)。所有列都被創建為可為空的,並且沒有定義主鍵或外鍵——它們對於查詢無關緊要,並且表永遠不會直接更新。一切的預設排序規則是
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
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
INSERT INTO … 使用製表符
插入
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
批量插入
現在,當我們創建一個也被
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)
數據被
page
壓縮並且也在69480 KB
:name rows reserved data index_size unused CompressedHeap_Destination 6365530 69512 KB 69480 KB 8 KB 24 KB
帶製表符的 BCP
BULK INSERT WITH TABLOCK
通過使用BCP IN
提示-h "TABLOCK"
,您可以獲得與 相同的結果。這是有道理的,他們在內部做同樣的事情--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T -h "TABLOCK"
結果大小為
69480 KB
BCP 輸入無製表符
使用 BCP 從目標表副本中的同一文件載入數據
標準 bcp 命令會生成非壓縮數據:
--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T
數據大小為
132272 KB
(行壓縮)。