2009-07-06 53 views
4

當前,我們的.NET應用程序在存儲器中構造了XML數據,我們堅持SQL Server數據庫。 XElement對象使用ToString()轉換爲字符串,然後存儲在數據庫中的varchar(MAX)列中。我們不想使用SQL XML數據類型,因爲我們不需要任何驗證,SQL在任何階段都不需要查詢XML。用於存儲在SQL Server數據庫中的XML的.NET壓縮

雖然這個實現工作正常,但我們希望通過在存儲XML之前壓縮XML來減小數據庫的大小,並在檢索它之後對其進行解壓縮。有沒有人有任何壓縮XElement對象的示例代碼(並且解壓縮也會很棒)?另外,我需要對數據庫列的數據類型進行哪些更改,以便充分利用此壓縮功能?

我再次調查了SQL Server 2005提供的XML數據類型,它提供的驗證開銷太高,我們無法考慮使用它。另外,雖然它在某種程度上壓縮了XML,但它並沒有.NET DeflateStream類那麼多。

我已經通過將我們使用的XML寫入磁盤測試了DeflateStream類,然後將壓縮版本保存爲新文件。結果非常好,一個16kb的文件下降到一個3kb的文件,所以這只是一個讓內存工作並將結果數據保存到數據庫的情況。有沒有人有任何示例代碼來做壓縮,並且我應該更改varcahr(MAX)colum鍵入可能varbinary?

在此先感謝

+0

壓縮Xml對於性能來說也是一個好主意 - 這給了我們應用程序的一個很大的性能提升,它被大量的Xml寫入到數據庫中。 – Justin 2009-07-06 20:55:31

回答

3

This article可以幫助你得到一個開始。

下面的代碼片斷可以壓縮一個字符串,並返回一個基本-64編碼的結果:

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); 
} 

編輯:順便說一句,你可能希望保存XML文本時使用CLOB格式,甚至因爲VARCHAR處理有長度非常有限 - 哪些XML通常可以快速超過。

+2

如果數據可以寫成字節數組而不是Base64字符串,最好是數據可以寫成字節數組,因爲編碼中的1/3擴展會吞噬壓縮的部分增益,至少在電線上。 – 2009-07-06 21:14:37

+0

@Steven - base-64編碼流的擴展量實際上取決於XML中的冗餘級別。有些溪流可能會變小,有些可能會變大。這很難預測。但是,您可以確定純二進制數據流將比base-64編碼數據流小。您將不得不對真實世界的數據進行一些測試,以查看壓縮因子是否被base-64編碼效率低下所抵消。 – LBushkin 2009-07-06 21:18:28

+0

GZip獲取的壓縮量取決於XML中的冗餘級別。幸運的是,即使在純文本通常具有的冗餘之上,XML也充滿了冗餘。然而,Base64始終將3個字節的8位數據擴展爲4個字節的7位密文。如果輸出被視爲nvarchar而不是varchar,那麼它再次加倍。另一方面,如果您實際在SQL Server中使用XML數據類型,則會有壓縮和索引組合。 – 2009-07-07 00:17:33

-2

我知道你標記了問題SQL 2005,但你應該考慮升級到SQL 2008,並使用它隨附的精彩新0123'。對於您的應用程序是開箱即用的,透明的,並且會爲您節省巨大的實施/測試/支持成本。

+1

據我所知,這些壓縮選項將無助於存儲XML。對於固定長度的數據類型,行壓縮非常有用,但這些數據類型並沒有真正修復。頁面壓縮適用於反覆存儲相同值的列(例如,對於1500行,當Status ='BackOrdered'時,頁面壓縮將存儲'BackOrdered'一次)。 – Vaccano 2012-01-30 23:22:37

2

我想你還應該重新測試XML列。我知道,它以二進制形式存儲,而不是文本。即使您實際上不需要額外的功能,它可能會更小,並且可能不會很差。

1

除了可能壓縮字符串本身(也許使用上面的LBushkin的Base64方法),你可能想要開始確保你殺死所有的空白。默認的XElement.ToString()方法使用「indenting」保存元素。如果您想確保剛剛獲得標籤和數據,則需要使用ToString(SaveOptions選項)方法(使用SaveOptions.DisableFormatting)。

相關問題