Как работает сортировка без учета регистра?


19

Тип сортировки по умолчанию в SQL Server позволяет индексировать строки без учета регистра, но регистр данных сохраняется. Как это на самом деле работает? Я ищу реальные гайки и болты, биты и байты, или хороший ресурс, который объясняет это подробно.

create table casetest (fruitnames nvarchar(50) not null);
create unique index IX_fruitnames on casetest(fruitnames);

insert into casetest values ('apples');
insert into casetest values ('Pears');
-- this insert fails
insert into casetest values ('pears');

-- this yields 'Pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

update casetest set fruitnames = 'pears' where fruitnames = 'pEArs'

-- this yields 'pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

Роберт Шелдон (Robert Sheldon) рассказывает, как использовать параметры сортировки в SQL Server . Это не охватывает, как работает сортировка. Меня интересует, как можно эффективно создать / запросить индекс, не заботясь о случае, одновременно сохраняя данные случая.


1
Вы можете эффективно запрашивать (например, используя поиск по индексу) нечувствительные к регистру строки к чувствительному к регистру полю, но это немного раздражает .
Джон Айсбренер

cocogorilla: пожалуйста, обратите внимание на примечание № 1, которое я только что добавил в конец своего ответа: сортировка «по умолчанию».
Соломон Руцкий

Ответы:


26

индексирование строк без учета регистра, но регистр данных сохраняется. Как это на самом деле работает?

На самом деле это не специфическое поведение SQL Server, а то, как все это работает в целом.

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

Данные, либо в табличном / кластеризованном индексе, либо в некластеризованном индексе, не содержат никакой информации о сортировке / сортировке. Это просто данные. Параметры сортировки (правила языка и культуры и чувствительность) - это просто метаданные, прикрепленные к столбцу и используемые при вызове операции сортировки (если она не переопределенаCOLLATEпункт), который будет включать в себя создание / перестроение индекса. Правила, определенные недвоичным сопоставлением, используются для генерации ключей сортировки, которые являются двоичными представлениями строки (ключи сортировки не нужны в двоичных сопоставлениях). Эти двоичные представления включают в себя все правила локали / культуры и выбранную чувствительность. Ключи сортировки используются для размещения записей в правильном порядке, но сами не хранятся в индексе или таблице. Они не хранятся (по крайней мере, я не видел эти значения в индексе и мне сказали, что они не хранятся), потому что:

  1. Они действительно не нужны для сортировки, так как в любом случае они будут в том же порядке, что и строки в таблице или индексе. Но физический порядок индекса - это просто сортировка, а не сравнение.
  2. Хотя их хранение может ускорить сравнение , оно также увеличит индекс, так как минимальный размер для одного символа составляет 5 байт, и это просто «накладные расходы» (структуры ключа сортировки). Большинство символов составляют 2 байта каждый, плюс 1 байт, если есть акцент, плюс 1 байт, если он в верхнем регистре. Например, «e» - это 7-байтовый ключ, «E» и «é» - это 8 байтов, а «É» - 9-байтовый ключ. Следовательно, не стоит хранить их в конце концов.

Существует два типа сопоставлений: SQL Server и Windows.

SQL Server

Параметры сортировки SQL Server (все имена , начинающиеся с SQL_) являются старые, предварительно SQL Server 2000 способ сортировки / сравнения (даже если SQL_Latin1_General_CP1_CI_ASэто все еще установки по умолчанию на американском английском операционки, довольно печально). В этой более старой упрощенной модели, не поддерживающей Юникод, каждая комбинация языкового стандарта, кодовой страницы и различной чувствительности получает статическое отображение каждого из символов в этой кодовой странице. Каждому символу присваивается значение (т. Е. Вес сортировки), чтобы обозначить, как он соотносится с остальными. Сравнения в этой модели, по-видимому, выполняют двухпроходную операцию:

  1. Во-первых, он удаляет все акценты (такие, что «  ü  » становится «  u  »), расширяет символы, такие как «  Æ  », в «  A  » и «  E  », затем выполняет первоначальную сортировку, чтобы слова были в естественном порядке (как вы бы ожидайте найти их в словаре).
  2. Затем он идет символ за символом, чтобы определить равенство на основе этих базовых значений для каждого символа. Эта вторая часть - то, что Мустаччо описывает в своем ответе .

Единственными значениями чувствительности, которые можно регулировать в этих сопоставлениях, являются: "case" и "accent" ("width", "kana type" и "selection selector" недоступны). Кроме того, ни один из этих параметров сортировки не поддерживает дополнительные символы (что имеет смысл, поскольку они являются специфичными для Unicode, и эти параметры сортировки применяются только к данным, не относящимся к Unicode).

Этот подход применяется только к не-Unicode VARCHARданным. Каждая уникальная комбинация локали, кодовой страницы, чувствительности к регистру и чувствительности к акценту имеет определенный «идентификатор сортировки», который вы можете увидеть в следующем примере:

SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
       COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
       COLLATIONPROPERTY(N'Latin1_General_100_CI_AS',     'SortID'); --  0

Единственная разница между первыми двумя сопоставлениями - это чувствительность к регистру. Третье сопоставление является сопоставлением Windows и поэтому не имеет таблицы статического сопоставления.

Кроме того, эти сопоставления должны сортироваться и сравниваться быстрее, чем сопоставления Windows, потому что это простой поиск символов для сортировки веса. Тем не менее, эти сопоставления также гораздо менее функциональны и, как правило, их следует избегать, если это вообще возможно.

Windows

Параметры сортировки Windows (имена которых не начинаются с SQL_) являются более новым (начиная с SQL Server 2000) способом сортировки / сравнения. В этой новой, сложной модели Unicode каждая комбинация языкового стандарта, кодовой страницы и различной чувствительности не получает статического сопоставления. Во-первых, в этой модели нет кодовых страниц. Эта модель назначает значение сортировки по умолчанию для каждого символа, а затем каждая локаль / культура может переназначать значения сортировки любому количеству символов. Это позволяет нескольким культурам использовать одни и те же символы по-разному. Это дает возможность естественной сортировки нескольких языков с использованием одного и того же сопоставления, если они не используют одни и те же символы (и если одному из них не нужно повторно назначать какие-либо значения и можно просто использовать значения по умолчанию).

Значения сортировки в этой модели не являются отдельными значениями. Они представляют собой массив значений, которые присваивают относительные веса базовой букве, любым диакритическим знакам (то есть акцентам), регистру и т. Д. Если параметры сортировки чувствительны к регистру, то используется часть «регистра» этого массива, в противном случае она игнорируется ( следовательно, нечувствителен). Если сортировка чувствительна к акценту, то используется «диакритическая» часть массива, в противном случае она игнорируется (следовательно, нечувствительна).

Сравнения в этой модели являются многопроходной операцией:

  1. Во-первых, строка нормализуется, так что различные способы представления одного и того же символа будут равны. Например, « ü » может быть одним символом / кодовой точкой (U + 00FC). Кроме того, можно объединить , не подчеркнутый « ˙U » (U + 0075) с Объединяя тремой « ··· » (U + 0308) , чтобы получить: « ü », который не только выглядит так же , когда оказывается (если нет проблем с ваш шрифт), но также считается такой же, как версия с одним символом (U + 00FC), если только не используется двоичное сопоставление (которое сравнивает байты вместо символов). Нормализация разбивает один символ на различные части, включая расширения для таких символов, как «  Æ  » (как отмечено выше для параметров сортировки SQL Server).
  2. Операция сравнения в этой модели идет символ за символом для каждой чувствительности . Ключи сортировки для строк определяются путем применения соответствующих элементов каждого массива параметров сопоставления символов, на основании которого чувствительность является «чувствительной». Значения ключа сортировки упорядочены по всем первичным значениям чувствительности каждого символа (базовому символу), за которыми следуют все вторичные значения чувствительности (диакритический вес), за которыми следует вес каждого символа и т. Д.
  3. Сортировка производится на основе рассчитанных ключей сортировки. Сгруппировав каждую чувствительность, вы можете получить другой порядок сортировки, чем при эквивалентном сопоставлении SQL Server при сравнении строк из нескольких символов, с акцентами, и сопоставление чувствительно к ударению (и даже в большей степени, если сопоставление также с учетом регистра).

Для получения более подробной информации об этой сортировке я в конечном итоге опубликую пост, в котором показаны значения ключей сортировки, как они рассчитываются, различия между SQL Server и Windows-сопоставлениями и т. Д. Но сейчас, пожалуйста, смотрите мой ответ на: Accent Sensitive Sort ( обратите внимание, что другой ответ на этот вопрос является хорошим объяснением официального алгоритма Unicode, но вместо этого SQL Server использует собственный, хотя и схожий алгоритм и даже пользовательскую таблицу весов).

Все параметры чувствительности можно регулировать в следующих сопоставлениях: «case», «accent», «width», «kana type» и «selection selector» (начиная с SQL Server 2017 и только для сопоставлений на японском языке). Кроме того, некоторые из этих параметров сортировки (при использовании с данными Unicode) поддерживают дополнительные символы (начиная с SQL Server 2012). Этот подход применяется как к данным, так NVARCHAR и к VARCHAR данным (даже не к Unicode-данным). Он применяется к данным, не относящимся к Unicode VARCHAR, сначала преобразовав значение в Unicode для внутреннего использования, а затем применив правила сортировки / сравнения.


Пожалуйста, обратите внимание:

  1. Для SQL Server не существует универсальной сортировки по умолчанию. Существует установка по умолчанию, которая отличается в зависимости от текущей настройки языка / языка ОС на момент установки (что, к сожалению, SQL_Latin1_General_CP1_CI_ASдля систем на английском языке в США, поэтому, пожалуйста, проголосуйте за это предложение ). Это можно изменить во время установки. Затем это сопоставление на уровне экземпляра устанавливает сопоставление для [model]БД, которое является шаблоном, используемым при создании новых БД, но сопоставление можно изменить при выполнении CREATE DATABASE, указав COLLATEпредложение. Это сопоставление на уровне базы данных используется для переменных и строковых литералов, а также по умолчанию для новых (и измененных!) Столбцов, когда COLLATEпредложение не указано (что имеет место для примера кода в вопросе).
  2. Для получения дополнительной информации о сопоставлениях / кодировках / Unicode, пожалуйста, посетите: Информация о сопоставлениях

5

Как правило, это реализуется с использованием таблиц сопоставления, которые присваивают определенную оценку каждому персонажу. Процедура сортировки имеет компаратор, который использует соответствующую таблицу, заданную по умолчанию или заданную явно, для сравнения строк, символ за символом, с использованием их показателей сопоставления. Если, например, конкретная таблица сопоставления присваивает оценку от 1 до «а», а от 201 до «А», а более низкая оценка в этой конкретной реализации означает более высокий приоритет, то «а» будет сортироваться перед «А». Другая таблица может назначать обратные оценки: 201 - «a» и 1 - «A», и порядок сортировки будет впоследствии обратным. Еще одна таблица может присваивать равные оценки «a», «A», «Á» и «Å», что приведет к нечувствительному к регистру и акценту сравнению и сортировке.

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


1
Только к сведению: эта информация верна только с точки зрения использования параметров сортировки SQL Server (то есть с именами, начинающимися с SQL_) при использовании VARCHARданных. Это не совсем верно для NVARCHARданных или VARCHARданных при использовании параметров сортировки Windows (имена не начинаются с SQL_).
Соломон Руцкий
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.