SQL Serverが、ページだけでなく、テーブル全体に対して一種の辞書圧縮をサポートするかどうか疑問に思っていました。
私が取り組んでいるシステムは、今日処理する大量のデータ用に最初は作成されていません。現在私が抱えている問題は次のとおりです。
アプリケーションでは、ユーザーが法的契約を作成することができます。これらの契約は標準化されていますが、ユーザーは必要に応じて契約の内容(テキスト)を調整できます。
これを容易にするために、各契約は標準化された契約テキストのコピーを作成します。実際には、ユーザーが契約テキストを編集することはほとんどないことがわかったので、多くの重複するデータを含むテーブルが作成されました。
通常、私はユースケースに合わせてDBモデルを変更しますが、これはレガシーシステムであり、そのような変更にはかなりの費用がかかります。それに代わる作業が行われているため、このような投資はそれほど簡単ではありません。
1ページだけでなく、テーブル全体に対して列ディクショナリ圧縮を行うことは可能ですか?
オンプレミスのSQLクラスターでSQL Server 2012を使用しています。
問題は、テーブルのサイズが80GB、DB全体のサイズが180GBであるということです。このテーブルは多くのスペースを占有し、SQLサーバーがデータをアンロードし続けるために十分なメモリがありません。
この表のデータは、PDF契約を表すために使用されます。ユーザーが契約の状態を変更するたびに、新しいPDFが生成され、監査目的で保存されているため、このテーブルで多くの読み取りが発生します。
読み取りはディスクに移動します(SQLサーバーがメモリからテーブルをアンロードし続けるため)。これにより、SANにIOの負担がかかります。
メモリの問題に取り組んでいますが、これには数週間かかります。現時点では、単にメモリを増設するだけでは選択肢にならないと言うだけで十分です。
私の考えは:短期的な解決策-テーブルのサイズを大幅に削減するデータを圧縮し、SQL Serverがテーブルをメモリに保持できるようにすることで、IOの負担を軽減します。 SAN上。
1ページだけでなく、テーブル全体に対して列ディクショナリ圧縮を行うことは可能ですか?
SQL Serverの組み込み圧縮について説明している状況では、おそらく何も起こりません。ドキュメントはNVARCHAR(MAX)
列に格納され、非ASCII文字を許可し、4,000文字を超える値を許可すると想定しています。オフページ値は、SQL Serverのどの方法(行圧縮、ページ圧縮、またはそれらに付属するUnicode圧縮)でも圧縮されないため、ほとんどの場合、すべてのドキュメントが変更されることはありません。
つまり、SQL Serverが自動的に実行できることはありません。
可能なオプション:(これは少し手動でハックです)
2016以降またはAzure SQLを使用している場合[1] [2] 次に、COMPRESS
/DECOMPRESS
関数を使用して、代わりにVARBINARY列に小さなBLOBとしてデータを格納できます。アプリケーションに対して透過的な方法でこれを行うには、データを格納するバッキングテーブルを作成し、実際のテーブルを、これから選択し、受信データを圧縮する_INSTEAD OF
_トリガーを持つビューに置き換えます。 。すでに大量のデータがある場合、展開に長い時間がかかる可能性があります。既存のコンテンツを圧縮するための何時間ものメンテナンスウィンドウの必要性をなくすには、バッキングテーブルにNVARCHAR(MAX)
列とVARBINARY(MAX)
列の両方があり、ビューはDocumentText = ISNULL(DECOMPRESS(CompressedText), UncompressedText)
で決定します。次に、プロセスがテーブルをゆっくりと処理して行のバッチを一度に圧縮し、ロックの問題を回避するのに十分なだけバッチを小さくして、本番環境でプロセスを処理できるようにします。
もちろん、データ層だけでなくアプリケーションにも影響を与えることができる場合は、ネットワーク転送とストレージとメモリを節約するため、代わりにドキュメントの圧縮を実装する方が効率的ですデータベースサーバー。
多くのドキュメントが完全に同一である場合、重複排除の方が個別に圧縮するよりも大きな利点が得られる可能性があります。これは、同様の手法を使用して行うことができます。メインテーブル内のそれらへの参照。バッキングテーブルプラスビューアンドトリガーメソッドを使用するか、アプリケーションのデータ操作レイヤーの他の場所に配置します。 2016/Azure(またはCLRの使用がオプションの場合)では、保存されたドキュメントも圧縮して、スペースを節約できます。
テンプレートから構築されているためにドキュメントの多くがほぼ同一である場合の別のオプションは、テンプレートと差分を保存することですが、文字列の差分とパッチを実行することは想像できないので、これはおそらくアプリケーション層またはCLRを介して実装する必要がありますTSQLは、十分に効率的な場所です。これは、ドキュメントが非圧縮形式(RTFファイル、古いOffice形式、マークダウンテキスト、最近のMS Office形式やPDFではない)で保存されている場合にのみ機能します。最初の変更後は異なります。
これらのアイデアは複雑さを追加し、書き込みパフォーマンスの低下をもたらすため、これらのネガティブを考慮して判断する必要があります。同様の状況で自分でアイデアを試してみています従来のアプリケーションでテキスト形式の大量の漬物データ(合計で数十GB、アイテムあたり平均数千文字)を収集します。完了したら、結果を共有する許可を取得できるかどうかを確認します。
-
[1]質問は後で更新され、彼らのケースではSQL2012が使用されていることに注意してください-重複排除方法は引き続き機能します。圧縮方法は同じような状況の他のユーザーに役立つため、回答には残しました。実際、SQL Server 2012では、カスタムCLRモジュールを使用して圧縮を実装することが可能ですhttp://aboutsqlserver.com/2015/04/07/ compressing-lob-xml-data-in-the-database / は、クイック検索の最初の見栄えの良い例ですが、他にもたくさんあります。
[2]以下のコメントでPaulが述べたように、2017でLOBサポートは圧縮列ストアインデックスに提供されるため、SQL Serverの最近の十分なバージョンを使用している人々が調査するためのもう1つの方法となります。
使用可能な圧縮のタイプ(ページまたは行)について誤解があるかもしれません。 1ページとはどういう意味ですか?
あなたの説明によると、私はあなたのシナリオではページ圧縮が行圧縮よりもうまく機能するかもしれないと信じています。しかし、SQLサーバーは1つだけでなく、すべてのデータページを圧縮します。インデックスまたはテーブル全体を圧縮できます。
ページレベルの圧縮は、日付、文字、XMLなどの繰り返しデータに適しています。
行レベルの圧縮は、数値など、定義された幅のデータ型に適しています。たとえば、列がINTとして定義されており、レコードがすべてのスペースを満たさない場合、その場合、バイト数は減少します。指定されたものよりスペースを取らない長い文字も圧縮されます。
--Test row compression.
ALTER TABLE table1 REBUILD WITH (data_compression = row)
EXEC sp_spaceused table1
--Test page compression.
ALTER TABLE table1 REBUILD WITH (data_compression = page)
EXEC sp_spaceused table1
--can estimate the saving for an index, tables or partition
sp_estimate_data_compression_savings
https://docs.Microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-estimate-data-compression-savings-transact-sql?view=sql-server- ver15 (特定のエディションでのみ使用可能)