web-dev-qa-db-ja.com

空のページ圧縮テーブルに一括挿入して完全に圧縮できますか?

読み取り専用レポートのためにSQL Server 2016に定期的にロードする必要のある大きなテーブル(幅が約1000万行)がたくさんあります。これらのテーブルをディスク上で可能な限り小さくしたいと思います。これは、ロードまたはクエリのパフォーマンスの向上以上に重要です。

これは、これ以上インデックスを作成する必要がないテーブルに対して私が行っていることです。

  1. DATA_COMPRESSION=PAGEを使用してテーブルを作成します。
  2. Bcpを使用して、フラットファイルから新しいテーブルにデータを一括挿入します。

テーブルの列タイプは、varchar(512以下、最大ではない)、float、tinyint、またはdate(datetimeではない)です。すべての列はnull可能として作成され、主キーまたは外部キーは定義されていません。これらはクエリに関係なく、テーブルが直接更新されることはありません。すべてのデフォルトの照合はSQL_Latin1_General_CP1_CI_ASです。

これを行うと、ページデータ圧縮がヒープに適用されたことをsys.allocation_unitsで確認でき、sys.partitionsでFILL FACTORが正しく0(100%)であることを確認できます。テーブルは非圧縮テーブルよりもはるかに小さいので、圧縮は完了したと思いました。

ただし、同じオプションDATA_COMPRESSION=PAGEを使用して再構築すると、圧縮済みのテーブルが約30%小さくなります。データページあたり約17行からページあたり25行になっているようです。 (ただし、1回だけです。その後再構築しても、最初の再構築よりも小さくはなりません。)

質問

だから私の質問は:(a)ここで何が起こっているのですか? (b)データが読み込まれた後に再構築する必要なしにテーブルを読み込むときに、この非常に小さな圧縮サイズを直接取得する方法はありますか?

7
Caitlin M. Shaw

@ HandyD は完全に正しいです。ヒープに挿入するときに圧縮を取得するために、他のいくつかの方法を強調したいだけです。

同じドキュメントから

ヒープがページレベルの圧縮用に構成されている場合、ページは次の方法でのみページレベルの圧縮を受け取ります。

  • データは一括最適化を有効にして一括インポートされます。
  • データはINSERT INTO ... WITH(TABLOCK)構文を使用して挿入され、テーブルには非クラスター化インデックスがありません。
  • PAGE圧縮オプションを指定してALTER TABLE ... REBUILDステートメントを実行すると、テーブルが再構築されます。

これによると、最小限に記録された一括挿入を活用するか、INSERT INTO ... WITH (TABLOCK)を使用して、再構築せずにPAGE圧縮を取得できます。


(a)ここで何が起こっているのですか? (b)データが読み込まれた後に再構築する必要なしにテーブルを読み込むときに、この非常に小さな圧縮サイズを直接取得する方法はありますか?

ヒープに挿入するときにPAGE圧縮を取得するルールがあります。圧縮を取得するには、bcpコマンドに-h "TABLOCK"を追加します。

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

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 IN TABLOCK

BULK INSERT WITH TABLOCKヒントとBCP INを使用すると、-h "TABLOCK"と同じ結果を得ることができます。 これは理にかなっています、彼らは内部的に同じことをします

--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T -h "TABLOCK"

結果のサイズは69480 KB

BLOCK IN WITH TABLOCK

BCPを使用して、宛先テーブルのコピー内の同じファイルからデータをロードする

そして標準のbcpコマンドは非圧縮データになります:

--bcp TEST.dbo.CompressedHeap_Destination2 IN E:\Data\HeapData.bcp -c -T 

132272 KBのデータサイズ(行圧縮)。

8
Randi Vertongen

圧縮に関する Docs 記事によると:

DML操作の一部としてヒープに割り当てられた新しいページは、ヒープが再構築されるまでPAGE圧縮を使用しません。圧縮を削除して再適用するか、クラスター化インデックスを作成して削除して、ヒープを再構築します。

これはあなたが見ているものと一致しているようです。再構築するまでは、実際にはテーブルが圧縮されていないようです。圧縮されていないテーブルにデータを読み込んでみて、ページあたり平均17行かどうか、またはこれが減少するかどうかを確認できます。それが変わらない場合は、圧縮されておらず、再構築が必要です。

クラスタ化インデックスをテーブルに追加することもできます。これにより、データの一括読み込み後にテーブルが圧縮解除/低圧縮されるのを防ぐことができます。

5
HandyD