2009-07-06 18 views
4

現在、.NETアプリケーションは、SQL Serverデータベースに永続化するメモリ内にXMLデータを構築します。 XElementオブジェクトはToString()を使用して文字列に変換され、DBのvarchar(MAX)列に格納されます。検証は必要ないため、SQLではどの段階でもXMLをクエリする必要がないため、SQL XMLデータ型を使用する必要はありません。SQL Serverデータベースに格納するXMLの.NET圧縮

この実装は正常に動作しますが、XMLを圧縮する前にXMLを圧縮し、取り出した後に解凍してデータベースのサイズを縮小したいと考えています。誰もXElementオブジェクトを圧縮するためのサンプルコードを持っていますか(また、解凍も素晴らしいでしょう)?また、この圧縮を完全に利用できるように、データベース列のデータ型にどのような変更を加える必要がありますか?

私はSQL Server 2005のXMLデータ型を再度調査しました。このデータベリファイのオーバーヘッドは、使用するには高すぎます。また、XMLを幾分圧縮しますが、.NET DeflateStreamクラスほどの圧縮はありません。

DeflateStreamクラスは、使用するXMLをディスクに書き込んだ後、新しいファイルとして保存することでテストされています。結果は素晴らしいです、16kbのファイルは3kbのファイルになりますので、これをメモリ上で動作させ、その結果のデータをDBに保存することはできません。誰も圧縮を行うためのサンプルコードがありますか、varbah(MAX)columをvarbinaryに変更する必要がありますか?事前

+0

Xmlの圧縮もパフォーマンスには良いアイデアです。これにより、多くのXmlがデータベースに書き込まれたときにボトルネックになっていたアプリケーションのパフォーマンスが大幅に向上しました。 – Justin

答えて

3

This article

おかげで、あなたがスタートを得るのを助けることがあります。

public static string Compress(string text) 
{ 
byte[] buffer = Encoding.UTF8.GetBytes(text); 
MemoryStream ms = new MemoryStream(); 
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true)) 
{ 
    zip.Write(buffer, 0, buffer.Length); 
} 

ms.Position = 0; 
MemoryStream outStream = new MemoryStream(); 

byte[] compressed = new byte[ms.Length]; 
ms.Read(compressed, 0, compressed.Length); 

byte[] gzBuffer = new byte[compressed.Length + 4]; 
System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length); 
System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4); 
return Convert.ToBase64String (gzBuffer); 
} 

EDIT:

次のスニペットは、ベース64コード化された結果を文字列を圧縮して返すことができさておき、あなたがテキストとしてXMLを格納するときのVARCHAR持っているためでもCLOB形式を使用することをお勧めしますと非常に限られた長さ - XMLはしばしばすばやく超えることができます。

+2

エンコーディングの1/3の拡張が少なくともワイヤー上の圧縮のゲインの一部を呑み込むため、データをBase64ストリングではなくバイト配列として書き込むことができれば最適です。 –

+0

@Steven - Base64コード化ストリームの拡張量は、実際にはXMLの冗長性のレベルに依存します。一部のストリームは小さくなり、一部は大きくなることがあります。予測が難しい。しかし、純粋なバイナリストリームがベース64でコード化されたストリームよりも小さくなることは確かです。圧縮係数がBase-64のコーディングの非効率性によって相殺されるかどうかを確かめるためには、実世界のデータについていくつかのテストを行う必要があります。 – LBushkin

+0

GZipの圧縮量は、XMLの冗長性のレベルによって異なります。幸いにも、XMLは一般的な冗長性の上にあっても、冗長性でいっぱいです。しかし、Base64は、3バイトの8ビットデータを4バイトの7ビット暗号テキストに一貫して展開します。出力がvarcharではなくnvarcharとして扱われる場合、出力は再び倍増します。一方、SQL Serverで実際にXMLデータ型を使用する場合、圧縮とインデックス作成の組み合わせがあります。 –

-2

SQL 2005の質問にタグが付いていることは知っていますが、SQL 2008にアップグレードし、付属のすばらしい新しいcompression capabilitiesを使用することを検討する必要があります。すぐに使える、アプリケーションの透過性があり、実装/テスト/サポートのコストを大幅に節約できます。

+1

私が理解しているように、これらの圧縮オプションはXMLの格納に役立ちません。行圧縮は、実際には固定されていない固定長のデータ型に適しています。そして、ページ圧縮は、同じ値を何度も保持する列のためです(つまり、ステータス= 'BackOrdered'の場合、1500回のページ圧縮で「BackOrdered」が1回だけ格納されます)。 – Vaccano

2

また、XML列を再テストする必要があると思います。バイナリ形式ではなく、テキストとして保存します。追加機能を実際に必要としない場合でも、それは小さくて済む可能性があります。

+1

+1 - はい、実際にSQL ServerのXMLデータ型XMLに格納されているXMLを「トークン化」して、関連付けられたスキーマの有無にかかわらず、対応するVARCHAR(MAX)フィールドよりも小さくなります。 –

+0

私はそれと矛盾する結果を得ています。私は本当のXML列を持っていて、私の結果によって混乱しています。 dataLength(cast(myxml as nvarchar(max)))> len(cast(myxml as nvarchar(max)))> datalength(myxml)とはどういう意味ですか? – BlueMonkMN

+0

私は分かりません。しかし、サイズはすべてではありません。パフォーマンスをテストします。 –

1

上記のLBushkinのBase64メソッドを使用して文字列自体を圧縮するだけでなく、おそらくすべての空白を消去することから始めることをお勧めします。デフォルトのXElement.ToString()メソッドは、要素を「字下げ」で保存します。タグとデータを取得したことを確認するには、ToString(SaveOptionsオプション)メソッド(SaveOptions.DisableFormattingを使用)を使用する必要があります。

+1

コンパクトで機械読み取り可能なXMLが必要な場合は、余分な空白とインデントをすべて削除することをお勧めします。あなたがそれを圧縮しようとするなら、ランレングス符号化は害の大部分を取り除くでしょう。同様に、サーバ上で解析された場合、空白は格納されたサイズではなくワイヤ上のサイズにのみ影響します。 –

関連する問題