Параметры сортировки и кодовые страницы

In-Memory OLTP имеет ограничения на поддерживаемые кодовые страницы для столбцов типа (var)char в таблицах, оптимизированных для памяти, а также на поддерживаемые параметры сортировки, используемые в индексах и нативно скомпилированных хранимых процедурах.

Кодовая страница для значения char (var)определяет сопоставление символов и байтового представления, хранящегося в таблице. Например, с кодовой страницей Windows Latin 1 (1252; по умолчанию SQL Server), символ 'a' соответствует байту 0x61.

Кодовая страница значения (var)char определяется параметрами сортировки, связанными со значением. Например, сортировка SQL_Latin1_General_CP1_CI_AS имеет связанную кодовую страницу 1252.

Порядок сортировки значения наследуется из порядка сортировки базы данных или может быть явно указан с помощью ключевого слова COLLATE. Параметры сортировки базы данных нельзя изменить, если база данных содержит оптимизированные для памяти таблицы или скомпилированные в собственном коде хранимые процедуры. Следующий пример задает параметры сортировки базы данных и создает таблицу, которая содержит столбец с другой сортировкой. В базе данных используется сортировка строк без учёта регистра, основанная на латинском алфавите.

Индексы можно создавать только в строковых столбцах, если они используют параметры сортировки BIN2. Переменная LastName использует параметры сортировки BIN2. FirstName использует базу данных по умолчанию, которая CI_AS (без учета регистра, с учетом акцента).

Это важно

Нельзя упорядочивать или группировать по строковым столбцам индекса, которые не используют сопоставление BIN2.

CREATE DATABASE IMOLTP  
  
ALTER DATABASE IMOLTP ADD FILEGROUP IMOLTP_mod CONTAINS MEMORY_OPTIMIZED_DATA  
ALTER DATABASE IMOLTP ADD FILE( NAME = 'IMOLTP_mod' , FILENAME = 'c:\data\IMOLTP_mod') TO FILEGROUP IMOLTP_mod;  
--GO  
  
--  set the database collations  
ALTER DATABASE IMOLTP COLLATE Latin1_General_100_CI_AS  
GO  
  
--  
USE IMOLTP   
GO  
  
-- create a table with collation  
CREATE TABLE Employees (  
  EmployeeID int NOT NULL ,   
  LastName nvarchar(20) COLLATE Latin1_General_100_BIN2 NOT NULL INDEX IX_LastName NONCLUSTERED,   
  FirstName nvarchar(10) NOT NULL ,  
  CONSTRAINT PK_Employees PRIMARY KEY NONCLUSTERED HASH(EmployeeID)  WITH (BUCKET_COUNT=1024)  
) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA)  
GO  

Следующие ограничения применяются к таблицам, оптимизированным для обработки в памяти, и к хранимым процедурам, скомпилированным в машинный код:

  • Столбцы (var)char в таблицах, оптимизированных для памяти, должны использовать коллирование с кодовой страницей 1252. Это ограничение не применяется к столбцам n(var)char. Следующий код извлекает все параметры сортировки 1252:

    -- all supported collations for (var)char columns in memory-optimized tables  
    select * from sys.fn_helpcollations()  
    where collationproperty(name, 'codepage') = 1252;  
    

    Если вам нужно хранить символы, отличные от латиницы, используйте столбцы n(var)char.

  • Индексы на столбцах (n)(var)char можно указать только с колляцией BIN2 (см. первый пример). Следующий запрос извлекает все поддерживаемые параметры сортировки BIN2:

    -- all supported collations for indexes on memory-optimized tables and   
    -- comparison/sorting in natively compiled stored procedures  
    select * from sys.fn_helpcollations() where name like '%BIN2'  
    

    При доступе к таблице с помощью интерпретированного Transact-SQL можно использовать ключевое слово COLLATE для изменения сортировки в выражениях или операциях сортировки. Пример этого см. в последнем примере.

  • Скомпилированные хранимые процедуры не могут использовать параметры, локальные переменные или строковые константы типа (var)char, если сортировка базы данных не является сортировкой по кодовой странице 1252.

  • Все выражения и операции сортировки внутри нативно скомпилированных хранимых процедур должны использовать сравнения BIN2. Это значит, что все операции сравнения и сортировки основаны на точках кода Юникода символов (двоичных представлений). Например, все сортировки чувствительны к регистру ("Z" идет перед "a"). При необходимости используйте значение Transact-SQL для нечувствительной к регистру сортировки и сравнения.

  • Усечение данных UTF-16 не поддерживается внутри нативно скомпилированных хранимых процедур. Это означает, что значения n(var)char(n) не могут быть преобразованы в тип n(var)char(i), если параметры< сортировки имеют свойство _SC. Например, следующее не поддерживается:

    -- column definition using an _SC collation  
     c2 nvarchar(200) collate Latin1_General_100_CS_AS_SC not null   
    -- assignment to a smaller variable, requiring truncation  
     declare @c2 nvarchar(100) = '';  
     select @c2 = c2  
    

    Функции обработки строк, такие как LEN, SUBSTRING, LTRIM и RTRIM с данными UTF-16, не поддерживаются внутри скомпилированных в собственном коде хранимых процедур. Эти функции обработки строк нельзя использовать для значений n(var)char, имеющих параметры сортировки _SC.

    Объявите переменные с помощью типов, которые достаточно большие, чтобы избежать усечения.

В следующем примере показаны некоторые последствия и обходные пути для ограничений сортировки в In-Memory OLTP. В примере используется таблица Employees, указанная выше. В этом примере перечислены все сотрудники. Обратите внимание, что для LastName из-за двоичной сортировки имена с заглавных букв сортируются до имен с прописными буквами. Таким образом, "Томас" приходит до "нолана", так как символы верхнего регистра имеют более низкие кодовые точки. FirstName имеет параметры сортировки без учета регистра. Таким образом, сортировка выполняется по букве алфавита, а не по кодовой точке символов.

-- insert a number of values  
INSERT Employees VALUES (1,'thomas', 'john')  
INSERT Employees VALUES (2,'Thomas', 'rupert')  
INSERT Employees VALUES (3,'Thomas', 'Jack')  
INSERT Employees VALUES (4,'Thomas', 'annie')  
INSERT Employees VALUES (5,'nolan', 'John')  
GO  
  
-- ===========  
SELECT EmployeeID, LastName, FirstName FROM Employees  
ORDER BY LastName, FirstName  
GO  
  
-- ===========  
-- specify collation: sorting uses case-insensitive collation, thus 'nolan' comes before 'Thomas'  
SELECT * FROM Employees  
ORDER BY LastName COLLATE Latin1_General_100_CI_AS, FirstName  
GO  
  
-- ===========  
-- retrieve employee by Name  
-- must use BIN2 collation for comparison in natively compiled stored procedures  
CREATE PROCEDURE usp_EmployeeByName @LastName nvarchar(20), @FirstName nvarchar(10)  
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER  
AS BEGIN ATOMIC WITH   
(  TRANSACTION ISOLATION LEVEL = SNAPSHOT,  
  LANGUAGE = N'us_english'  
)  
  SELECT EmployeeID, LastName, FirstName FROM dbo.Employees  
  WHERE   
    LastName = @LastName AND  
    FirstName COLLATE Latin1_General_100_BIN2 = @FirstName  
  
END  
GO  
  
-- this does not return any rows, as EmployeeID 1 has first name 'john', which is not equal to 'John' in a binary collation  
EXEC usp_EmployeeByName 'thomas', 'John'  
  
-- this retrieves EmployeeID 1  
EXEC usp_EmployeeByName 'thomas', 'john'  

См. также

In-Memory OLTP (оптимизацияIn-Memory)