Cara alternatif untuk kompres NVARCHAR (MAX)?

14

Saya mencoba mengompres beberapa tabel yang memiliki NVARCHAR(MAX)bidang. Sayangnya, rowdan pagekompresi tidak memiliki dampak keinginan (hanya ~ 100/200 MB disimpan untuk tabel 20 GB). Selain itu, saya tidak dapat menerapkan kompresi penyimpanan kolom dan penyimpanan kolom karena tidak mendukung kompresi NVARCHAR(MAX)bidang.

Adakah yang tahu kalau saya punya alternatif di sini?

Saya juga menebak rowdan pagekompresi tidak memiliki efek karena konten NVARCHAR(MAX)kolomnya unik.

Gotqn
sumber
2
Apakah nilai kolom pasti lebih luas dari 8000 karakter? mis. SELECT MAX (CAST (LEN (widecolumn) AS BIGINT)) DARI dbo.largeTable Kalau tidak, Anda bisa mengubahnya menjadi varchar biasa dan menerapkan kolomstore berkerumun.
wBob
@wBob Bahkan jika nilai terbesarnya hanya 2000 karakter, tidakkah konversi menjadi VARCHARberpotensi menyebabkan kehilangan data jika karakter dari lebih dari 1 Halaman Kode digunakan? Saya akan berpikir saran harus dikonversi ke NVARCHAR(4000)jika panjang maks tidak lebih besar dari 4000 karena semua nilai akan memenuhi syarat untuk Kompresi Unicode penuh. Namun, mungkin aman untuk mengasumsikan dari info dalam Pertanyaan bahwa nilainya lebih dari 4000 karakter, itulah sebabnya mereka saat ini tidak dikompres.
Solomon Rutzky

Jawaban:

16

Kompresi halaman dan baris tidak mengkompres BLOB .

Karena ukurannya, tipe data bernilai besar terkadang disimpan secara terpisah dari data baris normal pada halaman tujuan khusus. Kompresi data tidak tersedia untuk data yang disimpan secara terpisah.

Jika Anda ingin mengompresi BLOB, Anda perlu menyimpannya VARBINARY(MAX)dan menerapkan algoritma kompresi aliran pilihan Anda. Sebagai contoh GZipStream. Ada banyak contoh cara melakukan ini, cukup cari GZipStream dan SQLCLR.

Remus Rusanu
sumber
10

Ada (sekarang) berpotensi dua cara untuk mencapai kompresi khusus:

  1. Mulai di SQL Server 2016 ada fungsi built-in untuk COMPRESS dan DECOMPRESS . Fungsi-fungsi ini menggunakan algoritma GZip.

  2. Gunakan SQLCLR untuk mengimplementasikan algoritma apa pun yang Anda pilih (seperti @Remus disebutkan dalam jawabannya). Opsi ini tersedia dalam versi sebelum SQL Server 2016, kembali ke SQL Server 2005.

    GZip adalah pilihan yang mudah karena tersedia di dalam .NET dan di pustaka .NET Framework yang didukung (kode dapat berada dalam SAFEMajelis). Atau, jika Anda ingin GZip tetapi tidak ingin berurusan dengan pengkodean / penggelarannya, Anda dapat menggunakan fungsi Util_GZip dan Util_GUnzip yang tersedia dalam versi gratis dari perpustakaan SQL # SQLCLR (yang saya penulis).

    Jika Anda memutuskan untuk menggunakan GZip, apakah Anda mengkodekannya sendiri atau menggunakan SQL #, perlu diketahui bahwa algoritma yang digunakan dalam .NET untuk melakukan kompresi GZip berubah dalam Framework versi 4.5 menjadi lebih baik (lihat bagian "Keterangan" pada MSDN halaman untuk Kelas GZipStream ). Ini berarti:

    1. Jika Anda menggunakan SQL Server 2005, 2008, atau 2008 R2 - semua ditautkan ke CLR v 2.0 yang menangani versi Kerangka 2.0, 3.0, dan 3.5 - maka perubahan yang dibuat dalam Kerangka versi 4.5 tidak berpengaruh dan Anda sayangnya terjebak dengan .NET asli, algoritma sial.
    2. Jika Anda menggunakan SQL Server 2012 atau yang lebih baru (sejauh 2014 dan 2016) - semua terkait dengan CLR v 4.0 yang menangani versi Kerangka 4.0, 4.5.x, 4.6 - maka Anda dapat menggunakan algoritma yang lebih baru dan lebih baik. Satu-satunya persyaratan adalah Anda telah memperbarui .NET Framework di server yang menjalankan SQL Server menjadi versi 4.5 atau lebih baru.

    Namun, Anda tidak harus menggunakan GZip dan bebas menerapkan algoritma apa pun seperti.

TOLONG DICATAT: semua metode yang disebutkan di atas lebih dari sekadar "mengatasi" alih-alih menjadi pengganti yang sebenarnya, meskipun secara teknis "cara alternatif untuk mengompresi data NVARCHAR (MAX)". Perbedaannya adalah bahwa dengan Kompresi Data bawaan - rowdan page- yang ditawarkan oleh SQL Server, kompresi ditangani di belakang layar dan data masih dapat digunakan, dibaca, dan diindeks. Tetapi mengompresi data apa pun menjadi VARBINARYsarana Anda menghemat ruang, tetapi melepaskan beberapa fungsi. Benar, string 20k tidak dapat diindeks, tetapi masih dapat digunakan dalamWHEREklausa, atau dengan fungsi string apa pun. Untuk melakukan apa pun dengan nilai terkompresi khusus, Anda harus mendekompresnya dengan cepat. Saat mengompresi file biner (PDF, JPEG, dll.) Ini bukan masalah, tetapi pertanyaan ini khusus untuk NVARCHARdata.

Solomon Rutzky
sumber