Альтернативный способ сжатия NVARCHAR (MAX)?

14

Я пытаюсь сжать некоторые таблицы, которые имеют NVARCHAR(MAX)поля. К сожалению, rowи pageсжатие не имеет влияние желания (только ~ 100/200 MB сохраненное на 20 Гб таблицы). Кроме того, я не могу применить архивное сжатие хранилища столбцов и хранилищ столбцов, поскольку они не поддерживают сжатие NVARCHAR(MAX)полей.

Может кто-нибудь сказать, есть ли у меня какие-либо альтернативы здесь?

Я также предполагаю , что rowи pageсжатие не имеет эффекта , поскольку содержание NVARCHAR(MAX)столбцов является уникальным.

gotqn
источник
2
Значения столбца определенно шире, чем 8000 символов? например, SELECT MAX (CAST (LEN (widecolumn) AS BIGINT)) FROM dbo.largeTable В противном случае вы можете преобразовать их в обычный varchar и применить кластеризованное хранилище столбцов.
wBob
@wBob Даже если наибольшее значение было всего 2000 символов, не приведет ли преобразование к VARCHARпотере данных, если используются символы из более чем 1 кодовой страницы? Я думаю, что совет должен быть преобразован, NVARCHAR(4000)если максимальная длина не превышает 4000, потому что тогда все значения будут иметь право на полное сжатие Unicode. Тем не менее, из информации в вопросе, вероятно, можно с уверенностью предположить, что значения имеют длину более 4000 символов, поэтому в настоящее время они не сжимаются.
Соломон Руцкий,

Ответы:

16

Сжатие страниц и строк не сжимает большие двоичные объекты .

Из-за своего размера типы данных с большими значениями иногда хранятся отдельно от обычных данных строк на страницах специального назначения. Сжатие данных недоступно для данных, которые хранятся отдельно.

Если вы хотите сжать большие двоичные объекты, вам нужно сохранить их как VARBINARY(MAX)и применить алгоритм сжатия потоков по вашему выбору. Например GZipStream. Есть много примеров, как это сделать, просто найдите GZipStream и SQLCLR.

Ремус Русану
источник
10

Есть (сейчас) потенциально два способа выполнить пользовательское сжатие:

  1. Начиная с SQL Server 2016 есть встроенные функции для COMPRESS и DECOMPRESS . Эти функции используют алгоритм GZip.

  2. Используйте SQLCLR для реализации любого выбранного вами алгоритма (как @Remus упомянул в своем ответе). Эта опция доступна в версиях, предшествующих SQL Server 2016, начиная с SQL Server 2005.

    GZip - простой выбор, потому что он доступен в .NET и в поддерживаемых библиотеках .NET Framework (код может быть в SAFEсборке). Или, если вы хотите GZip, но не хотите заниматься его кодированием / развертыванием, вы можете использовать функции Util_GZip и Util_GUnzip , которые доступны в бесплатной версии библиотеки SQL # SQLCLR (автором которой я являюсь).

    Если вы решите использовать GZip, независимо от того, кодируете ли вы его самостоятельно или используете SQL #, учтите, что алгоритм, используемый в .NET для сжатия GZip, изменился в Framework версии 4.5 в лучшую сторону (см. Раздел «Замечания» в MSDN. страница для класса GZipStream ). Это означает:

    1. Если вы используете SQL Server 2005, 2008 или 2008 R2 - все они связаны с CLR v 2.0, которая поддерживает Framework версии 2.0, 3.0 и 3.5, - то изменения, внесенные в Framework 4.5, не действуют, и вы, к сожалению, застряли Оригинальный, отстойный алгоритм .NET.
    2. Если вы используете SQL Server 2012 или новее (до 2014 и 2016 гг.) - все они связаны с CLR v 4.0, которая обрабатывает версии Framework 4.0, 4.5.x, 4.6, - тогда вы можете использовать более новый и лучший алгоритм. Единственным требованием является обновление .NET Framework на сервере под управлением SQL Server до версии 4.5 или более поздней.

    Тем не менее, вы не должны использовать GZip и можете свободно реализовывать любой алгоритм, например.

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: все методы, упомянутые выше, являются более «обходными», а не фактическими заменами, даже если они являются технически «альтернативными способами сжатия данных NVARCHAR (MAX)». Разница заключается в том, что с помощью встроенного сжатия данных - rowи page- предлагаемый SQL Server, сжатие осуществляется за кадром , и данные еще можно использовать, читаемые, и индексируемые. Но сжатие любых данных VARBINARYозначает, что вы экономите место, но отказываетесь от некоторых функций. Правда, строка 20 КБ в любом случае не индексируется, но все же ее можно использовать вWHEREпредложение, или с любыми строковыми функциями. Чтобы сделать что-либо с пользовательским сжатым значением, вам нужно будет распаковать его на лету. При сжатии бинарных файлов (PDF, JPEG и т. Д.) Это не проблема, но этот вопрос относится только к NVARCHARданным.

Соломон Руцкий
источник