ページ圧縮を使用する場合の行オーバーヘッドは何ですか?


10

650 Numeric(19,4)列のテーブルを作成しました。実行してページ圧縮をオンにすると

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

私は得る

メッセージ1975、レベル16、状態1の
インデックス「PK_Mytable」の行の長さが、許容される最大長の「8060」バイトを超えています。

しかし、9バイトの650倍は5850バイトにすぎず、これは指定された制限の8060バイトからはかなりかけ離れています。

サーバーは、SQL Server 2016 SP1 CU2でWindows 2012 r2を実​​行しています

ページ圧縮を使用する場合の行オーバーヘッドは何ですか?

ここに私が何を意味するかを示すいくつかのコードがあります:

/* 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 2017

@StijnWynants; BigIntsには8バイトが使用されます。これは確かに事実ですが、列ストアインデックスを保証するのに十分な行が含まれていません。
Henrik Staun Poulsen 2017

回答:


13

クラスター化されたPK制約なしでテーブルを作成しようとすると、少し異なるエラーが発生します。

メッセージ1701、レベル16、状態1、行1最小行サイズが1567バイトの内部オーバーヘッドを含む8067になるため、テーブル 'Mytable'の作成または変更に失敗しました。これは、テーブルの最大許容行サイズである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個のそれぞれのための追加の2つのバイトを必要とするnumeric列に加え、bigintそしてintオーバーヘッドそれぞれの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 2017

1
@HenrikStaunPoulsenさらに重要なことは、SQL Serverは、データを圧縮できない可能性があると想定する必要があることです。したがって、データが8060バイト未満に圧縮される場合でも、SQL Serverは、圧縮できないデータの理論上の最大行サイズに基づいて行サイズを計算する必要があります。
AMtwo 2017

3日後も、行の圧縮に必要なバイト数には驚かされます。列ごとに2バイト。ページ圧縮により、さらに約3バイトが追加されます。だが; ご協力ありがとうございました。一番役に立ちました。
Henrik Staun Poulsen 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.