Когда `nvarchar / nchar` будет использоваться с SQL Server 2019?

11

В SQL Server 2019 Microsoft вводит поддержку UTF-8 для CHARи VARCHARтипов данных и говорит:

Эта функция может обеспечить значительную экономию памяти в зависимости от используемого набора символов. Например, изменение существующего типа данных столбца со строками ASCII с NCHAR (10) на CHAR (10) с использованием сортировки с поддержкой UTF-8 приводит к почти 50% снижению требований к хранилищу. Это сокращение вызвано тем, что NCHAR (10) требует 22 байта для хранения, тогда как CHAR (10) требует 12 байтов для той же строки Unicode.

UTF-8 поддерживает все сценарии, поэтому мы можем начать хранить данные Unicode в столбцах varcharи charстолбцах. И, как сказано в документации, это может уменьшить размер таблиц и индексов, и оттуда мы можем получить еще лучшую производительность, поскольку считывается меньшее количество данных.

Мне интересно , это значит , мы можем прекратить использовать nvarcharи ncharстолбцы , который реализует UTF-16?

Кто-нибудь может указать сценарий и причину, чтобы не использовать типы данных char с UTFкодировкой и продолжать использовать n-chars?

gotqn
источник
Почему бы вам не проверить это и не доложить? Также дайте нам знать, сколько усилий вы потратили на преобразование из nvarchar в varchar - сколько времени заняли таблицы изменения, сколько времени вы потратили на тестирование и с какими проблемами вы столкнулись.
Colin 't Hart
@ Colin'tHart Если нет каких-либо известных проблем или соображений, я планирую перенести данные, так как считаю, что чтение меньшего количества данных вообще приведет к повышению производительности системы. Насчет преобразования - конечно, это займет время, особенно если у вас есть индексы с данным столбцом - их нужно перестроить, но я думаю, что это хорошо окупится. Конечно, я собираюсь в ближайшее время протестировать влияние на производительность, просто посмотрев на любые проблемы, которые сделают миграцию ненужной.
получил
Обратите внимание, что SQL Server поддерживает сжатие Unicode для столбцов NVarchar при использовании сжатия PAGE или ROW. docs.microsoft.com/en-us/sql/relational-databases/…
Дэвид Браун - Microsoft,
1
Стоит отметить, что хотя UTF-8 может экономить место, если вы храните «ASCII-подобные данные», это не является сжатием само по себе и не должно ошибаться как таковое. Например, если вы храните в базе данных в основном китайские имена, вам будет хуже использовать CHARтипы UTF-8, чем типы Unicode (со сжатием или без, так как в конечном итоге данные должны быть сжаты для обработки). Также учтите, что собственный тип строки Windows - это Unicode, поэтому строки UTF-8 часто необходимо декодировать. Компромиссы означают, что маловероятно, что Nтипы будут удалены в ближайшее время.
Йерун Мостерт
1
«Убийственным приложением» № 1 для UTF-8 CHAR, вероятно, является SQL Server в Linux, если движок получает встроенную поддержку для обработки строк непосредственно как UTF-8 - здесь UTF-8 - это «собственный» набор символов (более или менее) и сохранение последовательности, поскольку UTF-16 является менее эффективной альтернативой. Конечно, использование Windows в тех местах, где вы уже используете CHAR, не повредит , поскольку параметры сортировки, ограничивающие символы, которые могут быть сохранены, никогда не были привлекательными.
Йерун Мостерт

Ответы:

6

это может уменьшить размер таблиц и индексов (выделение добавлено)

Уменьшение размера возможно только , если большинство персонажей, по существу [space], 0 - 9, A - Z, a - z, и некоторые основные знаки препинания. За пределами этого конкретного набора символов (в терминах практического использования, стандартных значений ASCII 32–126) вы будете в лучшем случае равны по размеру NVARCHAR/ UTF-16 или во многих случаях больше.

Я планирую перенести данные, так как считаю, что чтение меньшего количества данных вообще приведет к повышению производительности системы.

Быть осторожен. UTF-8 - это не волшебный переключатель «все исправить». При прочих равных условиях, да, чтение меньше улучшает производительность. Но здесь «все остальные вещи» не равны. Даже при хранении только стандартных символов ASCII (то есть: все символы имеют длину 1 байт, что требует вдвое меньше места по сравнению с сохранением в NVARCHAR), существует небольшое ухудшение производительности при использовании UTF-8. Я полагаю, что проблема связана с тем, что UTF-8 является кодировкой переменной длины, что означает, что каждый байт должен интерпретироваться так, как он читается, чтобы узнать, является ли он полным символом или является ли следующий байт его частью. Это означает, что все строковые операции должны начинаться с начала и проходить побайтово. С другой стороны,NVARCHAR / UTF-16 всегда составляет 2 байта (даже дополнительные символы состоят из двух 2-байтовых кодовых точек), поэтому все можно прочитать в 2-байтовых фрагментах.

В моем тестировании, даже с использованием только стандартных символов ASCII, сохранение данных в формате UTF-8 не дало экономии прошедшего времени, но было определенно хуже для процессорного времени. И это было без сжатия данных, поэтому, по крайней мере, было использовано меньше дискового пространства. Но при использовании сжатия пространство, необходимое для UTF-8, было только на 1% - 1,5% меньше. Таким образом, экономия места не достигается, а время процессора увеличивается для UTF-8.

Ситуация усложняется при использовании, NVARCHAR(MAX)так как сжатие Unicode не работает с этим типом данных, даже если значение достаточно мало для хранения в строке. Но если данные достаточно малы, они все равно должны извлечь выгоду из сжатия строк или страниц (в этом случае они действительно становятся быстрее, чем UTF-8). Однако данные вне строки не могут использовать сжатие. Тем не менее, сделав таблицу Clustered Columnstore Index, вы значительно уменьшите размер NVARCHAR(MAX)(даже если он все еще немного больше, чем UTF-8 при использовании Clustered Columnstore Index).

Кто-нибудь может указать сценарий и причину, чтобы не использовать типы данных char с кодировкой UTF

Определенно. На самом деле, я не вижу убедительной причины использовать его в большинстве случаев. Единственный сценарий, который действительно выигрывает от UTF-8, это:

  1. Данные в основном стандартные ASCII (значения 0 - 127)
  2. Это должен быть Unicode, потому что может потребоваться хранить более широкий диапазон символов, чем доступно на любой 8-битной кодовой странице (т.е. VARCHAR)
  3. Большая часть данных хранится вне строки (поэтому сжатие страниц даже не работает)
  4. У вас достаточно данных, которые вам нужно / вы хотите уменьшить размер по причинам, не связанным с производительностью запросов (например, уменьшить размер резервной копии, сократить время, необходимое для резервного копирования / восстановления и т. Д.)
  5. Вы не можете использовать Clustered Columnstore Index (возможно, использование таблицы ухудшает производительность в этом случае?)

Мои тесты показывают, что почти во всех случаях NVARCHAR работал быстрее, особенно когда данных было больше. Фактически, для 21 тыс. Строк со средним объемом 5 тыс. Символов на строку требуется 165 МБ для UTF-8 и 236 МБ для NVARCHARнесжатого. И все же он NVARCHARбыл в 2 раза быстрее по прошествии времени и, по крайней мере, в 2 раза быстрее (иногда больше) времени процессора. Тем не менее, это заняло еще 71 МБ на диске.

Помимо этого, я все еще не рекомендовал бы использовать UTF-8, по крайней мере, для CTP 2, из-за множества ошибок, которые я обнаружил в этой функции.

Для подробного анализа этой новой функции, включая объяснение различий между UTF-16 и UTF-8, и список этих ошибок, пожалуйста, смотрите мой пост:

Встроенная поддержка UTF-8 в SQL Server 2019: Спаситель или Лжепророк?

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

Поддержка UTF-8 дает вам новый набор опций. Потенциальная экономия места (без сжатия строк или страниц ) является одним из соображений, но выбор типа и кодировки, вероятно, следует делать в первую очередь на основе фактических требований к сравнению, сортировке, импорту и экспорту данных .

Возможно, вам придется изменить больше, чем вы думаете, так как, например, nchar(1)тип обеспечивает два байта памяти. Этого достаточно для хранения любого символа в BMP (кодовые точки от 000000 до 00FFFF). Некоторые символы в этом диапазоне будут кодироваться с помощью только 1 байта в UTF-8, в то время как другим потребуется 2 или даже 3 байта (см. Эту сравнительную таблицу для получения дополнительной информации). Поэтому для обеспечения покрытия того же набора символов в UTF-8 потребуется char(3).

Например:

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

дает знакомую ошибку:

Сообщение 8152, уровень 16, состояние 30, строка xxx.
Строка или двоичные данные будут обрезаны.

Или если флаг трассировки 460 активен:

Сообщение 2628, уровень 16, состояние 1, строка xxx
Строка или двоичные данные будут обрезаны в таблице «@T», столбец «UTF8». Усеченное значение: ''.

Расширение столбца UTF8 до char(2)или varchar(2)устранение ошибки для NCHAR(911):

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

Однако, если это, например NCHAR(8364), вам нужно будет расширить столбец до char(3)или varchar(3).

Также обратите внимание, что все параметры сортировки UTF-8 используют дополнительные символы, поэтому не будут работать с репликацией.

Помимо всего прочего, поддержка UTF-8 в настоящее время доступна только для предварительного просмотра, поэтому она недоступна для производственного использования.

Пол Уайт 9
источник