Поддержка UTF-8, SQL Server 2012 и UTT UTF8String - PullRequest
3 голосов
/ 25 января 2012

Исследуя преимущества и недостатки VARCHAR и NVARCHAR для SQL Server для моего конкретного приложения, я пришел к выводу, что было бы идеально, если бы SQL Server изначально поддерживал UTF8. Несколько сообщений SO указывают, что это не так, например ::10000

Похоже ли VARCHAR на 1990-е годы?

Каковы основные различия в производительности между типами данных SQL Server varchar и nvarchar?

Однако затем я наткнулся на эту статью в документации MSDN для SQL Server 2012, в которой показано, как создать пользовательский тип данных UTF8String:

http://msdn.microsoft.com/en-us/library/ff877964(v=sql.110).aspx

Похоже, что UDT позволит использовать преимущества 8 бит на символ для пространства (памяти, диска), в то же время будучи достаточно гибким для хранения любой строки, которая может быть представлена ​​в UTF-8. Это верно? Есть ли недостатки этой стратегии (например, затраты на производительность выполнения управляемого кода для каждой строки, ...)?

1 Ответ

2 голосов
/ 27 сентября 2015

Создание пользовательского типа, определенного пользователем, через SQLCLR - это , а не , в любом случае, вы получите замену любого собственного типа. Это очень удобно для создания чего-то для обработки специализированных данных. Но строки, даже другой кодировки, далеко не специализированы. Путь по этому маршруту для ваших строковых данных разрушит любое удобство использования вашей системы, не говоря уже о производительности, поскольку вы не сможете использовать любые встроенные строковые функции.

Если бы вы смогли сохранить что-либо на диске, эти выгоды были бы стерты из-за потери общей производительности. Хранение UDT осуществляется путем сериализации его в VARBINARY. Таким образом, чтобы выполнить любое сравнение строк ИЛИ сортировку вне «двоичного» / «порядкового» сравнения, вам придется преобразовать все остальные значения, одно за другим, обратно в UTF-8, чтобы затем выполнить сравнение строк, которое может учитывать языковые различия. И это преобразование должно быть сделано в рамках UDT. Это означает, что, как и тип данных XML, вы должны создать UDT для хранения определенного значения, а затем предоставить метод этого UDT для принятия строкового параметра для сравнения (т. Е. Utf8String.Compare(alias.field1) или, если определите оператор для введите Utf8string1 = Utf8string2, и оператор = получит строку в кодировке UTF-8, а затем выполните команду CompareInfo.Compare()).

В дополнение к вышеприведенным соображениям вам также необходимо учитывать, что передача значений назад и вперед через API SQLCLR имеет свою стоимость, особенно при использовании NVARCHAR(MAX) или VARBINARY(MAX) вместо NVARCHAR(1 - 4000) и VARBINARY(1 - 4000) соответственно (пожалуйста, не путайте это различие с намеками на использование SqlChars / SqlBytes против SqlString / SqlBinary).

Наконец (по крайней мере, с точки зрения использования UDT), пожалуйста, не забывайте о том факте, что запрашиваемый UDT - это пример кода . Единственное отмеченное тестирование является чисто функциональным, ничего не касается масштабируемости или «уроков, извлеченных после работы с ним в течение года». Код функционального теста показан здесь на следующей странице CodePlex, и перед тем, как приступить к принятию этого решения, его следует рассмотреть, поскольку он дает представление о том, как вам нужно написать свои запросы для взаимодействия с ним (что хорошо для поля или два, но не для большинства / всех строковых полей):

http://msftengprodsamples.codeplex.com/SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/Scripts/Test.sql

Учитывая количество сохраненных вычисляемых столбцов и добавленных индексов, действительно ли было сохранено какое-либо пространство? ; -)


Там, где пространство (диск, память и т. Д.) Является проблемой, у вас есть три варианта:

  1. Если вы используете SQL Server 2008 или новее и используете Enterprise Edition, вы можете включить Сжатие данных . Сжатие данных может (но не всегда) сжимать данные Unicode в полях NCHAR и NVARCHAR. Определяющими факторами являются:

    1. NCHAR(1 - 4000) и NVARCHAR(1 - 4000) используют стандартную схему сжатия для Unicode , но только начиная с SQL Server 2008 R2, И только для данных IN ROW, а не OVERFLOW! Это выглядит лучше, чем обычный алгоритм сжатия ROW / PAGE.
    2. NVARCHAR(MAX) и XML (и, я думаю, также VARBINARY(MAX), TEXT и NTEXT) данные, которые находятся в строке (не в строке на страницах LOB или OVERFLOW), могут быть сжаты по крайней мере на странице, и возможно также ROW сжатый (не уверен насчет последнего).
    3. Любые данные OFF ROW, LOB или OVERLOW = Нет сжатия для вас!
  2. Если вы используете версию более раннюю, чем 2008, или нет в Enterprise Edition, у вас может быть два поля: одно VARCHAR и одно NVARCHAR. Например, предположим, что вы храните URL-адреса, которые в основном все являются базовыми символами ASCII (значения 0–127) и, следовательно, вписываются в VARCHAR, но иногда содержат символы Unicode. Ваша схема может включать следующие 3 поля:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );
    

    В этой модели вы только ВЫБЕРИТЕ из вычисляемого столбца [URL]. Для вставки и обновления вы определяете, какое поле использовать, видя, изменяет ли преобразование входящее значение, которое должно иметь тип NVARCHAR:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
    
  3. Если у вас есть поля, в которых должны быть только символы, которые вписываются в определенную кодовую страницу расширенного набора символов ASCII, просто используйте VARCHAR.


PS Просто для ясности: новые _SC параметры сортировки, которые были введены в SQL Server 2012, просто позволяют:

  • встроенные функции для правильной обработки дополнительных символов / суррогатаПары и
  • лингвистические правила для дополнительных символов, которые используются для упорядочения и сравнения

Но даже без новых сопоставлений _SC вы все равно можете сохранить любой символ Unicode вТип с префиксом XML или N и извлечение его без потери данных.Однако при использовании более старых сопоставлений (т.е. без номера версии в имени) все дополнительные символы приравниваются друг к другу.Вам нужно использовать параметры сортировки _90 и _100, которые, по крайней мере, позволят вам сравнивать и сортировать двоичные / кодовые точки;они не могут принимать во внимание лингвистические правила, поскольку не имеют конкретных отображений дополнительных символов (и, следовательно, не имеют весов или правил нормализации).

Попробуйте выполнить следующее:

IF (N'?' = N'?') SELECT N'?' AS [TheLiteral], NCHAR(150150) AS [Generated];
IF (N'?' = N'?') SELECT N'?' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'?' COLLATE Tatar_90_CI_AI = N'?' COLLATE Tatar_90_CI_AI)
       SELECT N'? COLLATE Tatar_90_CI_AI' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'?' = N'?') SELECT N'?';

ВБД, имеющая сопоставление по умолчанию, оканчивающееся на _SC, только первый оператор IF вернет набор результатов, а поле "Сгенерированный" будет правильно отображать символы.

Но, если БД неимеют параметры сортировки по умолчанию, оканчивающиеся на _SC, и параметры сортировки не являются последовательностями сортировки _90 или _100, тогда первые два оператора IF возвращают наборы результатов, в которых поле "Сгенерировано" возвращает NULL, иполе «Literal» отображается правильно.

Для данных Unicode сортировка не имеет отношения к физической памяти.


ОБНОВЛЕНИЕ 2018-10-02

Хотя этот вариант пока не подходит, в SQL Server 2019 появилась встроенная поддержка UTF-8 в типах данных VARCHAR / CHAR.В настоящее время в нем слишком много ошибок, чтобы его можно было использовать, но если они исправлены, то это вариант для некоторых сценариев.Пожалуйста, смотрите мой пост " Собственная поддержка UTF-8 в SQL Server 2019: Спаситель или Лжепророк? " для подробного анализа этой новой функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...