Archive for the ‘DataSet Compression’ tag
How to Compress and Decompress a DataSet
Veri odaklı projelerde en sık kullanılan nesnelerin başında DataSet ve DataTable nesneleri yer alıyor. Ancak çalıştığımız veriler ve yapılar arttıkça, bu nesnelerle verileri taşımak oldukça zahmetli olabiliyor.
Şu anda yürüttüğüm projeden bir örnek vererek durumu açıklamak istiyorum;
Grafikte gördüğünüz senaryoda A noktasındaki merkezi sisteme B, C ve D noktalarından veri aktarımı gerekiyor. Aktarılacak veri 100 MB ile 5 GB arasında değişiyor. C ve D noktalarındaki bağlantı metro ethernet olduğu için herhangi bir sorun yaşamıyoruz ancak B noktasına giden hat bir noktaya kadar fiberken, B noktasının lokasyonunun getirdiği bir zorunluluktan dolayı bağlantı PDH oluyor ve ciddi oranda yavaşlık ortaya çıkıyor. Veri çekmek istediğimiz B sistemini günün 24 saati 400 ayrı lokasyondaki client kullandığı için hat üzerindeki yük, hattın kaldırabileceğinin çok üzerinde kalıyor. Bu noktadan çekmek istediğimiz veri dataset olarak 4.2 GB civarında.
Bu senaryoya bakacak olursak, durumun vehametini açıkça kavrayabiliriz.
Bu noktada uygulayacağımız basit bir çözümle, bu dataset’in boyutunu ciddi oranda minimize edebiliriz.
Visual Studio 2005 ile birlikte gelen System.IO.Compression alan adı zip ve gzip sıkıştırma algoritmalarını sunmakta. Bu makalede, bu algoritmaları kullanarak bir dataset nesnesini nasıl sıkıştırıp, nasıl açabileceğimizi göreceğiz.
İlk olarak sıkıştırma fonksiyonumuzu yazıyoruz;
public static byte[] CompressDataSet(DataSet ds)
{
ds.RemotingFormat = SerializationFormat.Binary;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, ds);
byte[] inbyt = ms.ToArray();
MemoryStream objStream = new MemoryStream();
DeflateStream objZS = new DeflateStream(objStream, CompressionMode.Compress);
objZS.Write(inbyt, 0, inbyt.Length);
objZS.Flush();
objZS.Close();
return objStream.ToArray();
}
İkinci aşamada sıkıştırmayı tersine çevirecek fonksiyonu yazıyoruz:
public static DataSet DecompressDataSet(byte[] bytDs, out int len)
{
System.Diagnostics.Debug.Write(bytDs.Length.ToString());
DataSet outDs = new DataSet();
MemoryStream inMs = new MemoryStream(bytDs);
inMs.Seek(0, 0);
DeflateStream zipStream = new DeflateStream(inMs, CompressionMode.Decompress, true);
byte[] outByt = ReadFullStream(zipStream);
zipStream.Flush();
zipStream.Close();
MemoryStream outMs = new MemoryStream(outByt);
outMs.Seek(0, 0);
outDs.RemotingFormat = SerializationFormat.Binary;
BinaryFormatter bf = new BinaryFormatter();
len = (int)outMs.Length;
outDs = (DataSet)bf.Deserialize(outMs, null);
return outDs;
}
public static byte[] ReadFullStream(Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
Son olarak bu fonksiyonların kullanımını örnekliyoruz:
private DataSet _dataSet = new DataSet();
private byte[] _compressedDs;
private DataSet _deCompressedDs;
private void button1_Click(object sender, EventArgs e)
{
DateTime start = DateTime.Now;
byte[] compressedDs = CompressDataSet(_dataSet);
File.WriteAllBytes("CompressedDataSetContent.txt", compressedDs);
int i;
_deCompressedDs = DecompressDataSet(compressedDs, out i);
_deCompressedDs.WriteXml("DecompressedDataSet.xml");
TimeSpan ts = DateTime.Now – start;
MessageBox.Show(string.Format("{0}dk, {1}sn, {2}sl", ts.Minutes, ts.Seconds, ts.Milliseconds));
}
Sonuçlara gelecek olursak, bu kodlarla sıkıştırdığımız 154.736 KB’lık bir dataset, 15 saniye gibi bir sürede 8.535 KB’ya düşüyor. Bu da senaryodaki gibi bir network ortamında oldukça önemli bir kazanım.












