2009-07-06 5 views
4

현재 .NET 응용 프로그램은 SQL Server 데이터베이스에 유지되는 메모리에 XML 데이터를 구성합니다. XElement 객체는 ToString()을 사용하여 문자열로 변환 된 다음 DB의 varchar (MAX) 열에 저장됩니다. 유효성 검사가 필요 없으며 SQL이 모든 단계에서 XML을 쿼리 할 필요가 없으므로 SQL XML 데이터 유형을 사용하지 않아도됩니다.SQL Server 데이터베이스에 저장할 XML의 .NET 압축

이 구현은 정상적으로 작동하지만 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); 
} 

편집 :

다음 코드는 기본-64 코딩 결과를 문자열을 압축하고 반환 할 수 있습니다 제쳐두고, 당신은 텍스트로 XML을 저장할 때 VARCHAR에가 있기 때문에 심지어 CLOB 형식을 사용할 수 있습니다으로 매우 제한된 길이 - XML은 종종 빠르게 초과 할 수 있습니다.

+2

인코딩의 1/3 확장이 적어도 유선에서 압축의 일부 이득을 삼켜 버리기 때문에 데이터를 Base64 문자열이 아닌 바이트 배열로 쓰는 것이 가장 좋습니다. –

+0

@Steven - Base-64로 코딩 된 스트림의 확장량은 실제로 XML의 중복 수준에 따라 달라집니다. 일부 스트림은 작아 지거나 일부 스트림이 더 커질 수 있습니다. 예측하기가 어렵습니다. 그러나 순수 바이너리 스트림이 Base-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 저장에 도움이되지 않습니다. 행 압축은 실제로 고정되지 않은 고정 길이 데이터 유형에 적합합니다. 그리고 페이지 압축은 동일한 값을 반복해서 저장하는 열에 대한 것입니다 (즉, Status = 'BackOrdered'가 1500 행이면 페이지 압축은 'BackOrdered'를 한 번 저장합니다). – 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을 원하면 여분의 공백 문자와 들여 쓰기를 모두 제거하는 것이 좋습니다. 당신이 그것을 압축하려고한다면, 런 - 랭스 인코딩은 많은 피해를 제거 할 것입니다. 마찬가지로, 서버에서 파싱 된 경우, 공백은 저장된 크기가 아닌 와이어를 통한 크기에만 영향을 미칩니다. –

관련 문제