індексування до рядків, нечутливих до регістру, але справа даних зберігається. Як це насправді працює?
Це насправді не поведінка, характерна для SQL Server, це лише те, як ці речі працюють взагалі.
Отже, дані - це дані. Якщо ви конкретно говорите про індекс, дані потрібно зберігати, як інакше, це вимагатиме кожного разу шукати в головній таблиці, щоб отримати фактичне значення, і немає можливості охоплювати індекс (у принаймні, не для типів рядків).
Дані в таблиці / кластерному індексі або некластеризованому індексі не містять ніякої інформації про порівняння / сортування. Це просто дані. Порівнювання (правила локалізації / культури та чутливості) - це лише метадані, приєднані до стовпця і використовуються при виклику операції сортування (якщо тільки це не перекритоCOLLATE
пункт), який би включав створення / відновлення індексу. Правила, визначені небінарним зіставленням, використовуються для генерації ключів сортування, які є двійковими представленнями рядка (сортування ключів є непотрібним у двійкових зіставленнях). Ці бінарні уявлення містять усі правила локалізації / культури та вибрані чутливості. Клавіші сортування використовуються для розміщення записів у належному порядку, але самі не зберігаються в індексі чи таблиці. Вони не зберігаються (принаймні, я не бачив цих значень в індексі, і мені сказали, що вони не зберігаються), оскільки:
- Вони справді не потрібні для сортування, оскільки вони просто будуть у тому ж порядку, що й рядки в таблиці чи індекс. Але фізичний порядок індексу - це лише сортування, а не порівняння.
- Хоча зберігання їх може зробити порівняння швидшими, це також зробить індекс більшим, оскільки мінімальний розмір для одного символу становить 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
це все ще установки по замовчуванням на американському англійською операційки, досить сумно). У цій старшій, спрощеній моделі, яка не використовується Unicode, кожній комбінації мови, кодової сторінки та різної чутливості надається статичне відображення кожного з символів на цій сторінці коду. Кожному символу присвоюється значення (тобто вага сортування) для позначення того, як воно зрівняється з іншими. Порівняння в цій моделі, схоже, виконують операцію з двома проходами:
- По-перше, він видаляє всі наголоси (такі, що " ü " стає " u "), розширює символи типу " Æ " на " A " і " E ", потім робить початковий сортування, щоб слова були в природному порядку (як би ви очікуємо знайти їх у словнику).
- Потім, він переходить символ за символом, щоб визначити рівність на основі цих базових значень для кожного символу. Ця друга частина - те, що описує Мустаччо у своїй відповіді .
Єдині чутливості, які можна регулювати в цих зіставленнях, є: "регістр" та "наголос" ("ширина", "тип кана" та "селектор варіації" недоступні). Крім того, жодне з цих зіставлень не підтримує додаткових символів (що має сенс, оскільки вони є специфічними для 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 кожній комбінації локалі, кодової сторінки та різної чутливості не надається статичне відображення. З одного боку, у цій моделі немає кодових сторінок. Ця модель присвоює значення сортування за замовчуванням кожному символу, і тоді кожна локаль / культура може повторно призначити значення сортування будь-якій кількості символів. Це дозволяє різним культурам використовувати одні й ті самі символи по-різному. Це може вплинути на можливість сортування декількох мов природним чином за допомогою одного і того ж зіставлення, якщо вони не використовують однакові символи (і якщо одному з них не потрібно повторно призначати будь-які значення та просто використовувати за замовчуванням).
Значення сортування в цій моделі не є одиничними значеннями. Вони являють собою масив значень, які присвоюють відносні ваги базовій літері, будь-якій діакритиці (тобто наголоси), кожуху тощо. Якщо зіставлення залежить від регістру, то використовується "регістр" цього масиву, інакше він ігнорується ( отже, нечутливий). Якщо зіставлення чутливе до акцентів, тоді використовується "діакритична" частина масиву, інакше вона ігнорується (отже, нечутлива).
Порівняння в цій моделі є багатопрохідною операцією:
- По-перше, рядок нормалізується так, що різні способи подання одного і того ж символу зрівняються. Наприклад, " ü " може бути одним символом / кодовою точкою (U + 00FC). Крім того, можна об'єднати , не підкреслений « ˙U » (U + 0075) з Об'єднуючи трьома « ··· » (U + 0308) , щоб отримати: « ü », який не тільки виглядає так само , коли виявляється (якщо немає проблем з ваш шрифт), але також вважається таким же, як і версія одного символу (U + 00FC), за винятком випадків, коли використовується двійкове порівняння (яке порівнює байти замість символів). Нормалізація розбиває один символ на різні фрагменти, що включає розширення для символів типу " Æ " (як зазначено вище для порівнянь на SQL Server).
- Операція порівняння в цій моделі має характер за символом для кожної чутливості . Клавіші сортування рядків визначаються шляхом застосування відповідних елементів масиву зіставлення кожного символу на основі яких чутливості "чутливі". Ключові значення сортування впорядковуються за всіма первинними чутливості кожного символу (базовим символом), за ними слідують усі вторинні чутливості (діакритична вага), а потім вага випадку кожного символу тощо.
- Сортування проводиться на основі розрахованих клавіш сортування. Коли кожна чутливість згрупована разом, ви можете отримати інший порядок сортування, ніж ви б при еквівалентному зіставленні SQL Server, коли порівнюєте рядки з декількох символів, а також наголоси, а порівняння чутливе до акцентів (і тим більше, якщо порівняння є також залежно від регістру).
Для отримання більш докладної інформації по цій сортуванні, я в кінцевому підсумку опублікувати пост , який показує , що - то ключові цінності, як вони розраховуються, відмінність між SQL Server і Windows , сортуванням і т.д. Але на даний момент, будь ласка , см моєї відповіді на: Accent Sensitive Sort ( зауважте, що інша відповідь на це питання є хорошим поясненням офіційного алгоритму Unicode, але натомість SQL Server використовує користувальницький, хоча й аналогічний, алгоритм і навіть власну таблицю ваги).
Усі чутливості можуть бути відрегульовані в цих зіставленнях: "регістр", "акцент", "ширина", "тип кана" та "селектор варіацій" (починаючи з SQL Server 2017, і лише для японських посилань). Також деякі з цих зіставлень (коли вони використовуються з даними Unicode) підтримують додаткові символи (починаючи з SQL Server 2012). Цей підхід застосовується як до даних, так NVARCHAR
і до VARCHAR
даних (навіть даних, що не стосуються Unicode). Він застосовується до даних, що не стосуються Unicode VARCHAR
, спочатку перетворюючи значення в Unicode внутрішньо, а потім застосовуючи правила сортування / порівняння.
Будь ласка, запиши:
- Не існує універсального порівняння за замовчуванням для SQL Server. Існує налаштування за замовчуванням, яке відрізняється залежно від поточного налаштування мови / мови ОС на момент встановлення (що, на жаль,
SQL_Latin1_General_CP1_CI_AS
для американських англійських систем, тому, будь ласка, проголосуйте за цю пропозицію ). Це можна змінити під час встановлення. Це зіставлення на рівні примірника потім встановлює зіставлення для [model]
БД, що є шаблоном, використовуваним при створенні нових БД, але порівняння може бути змінено при виконанні CREATE DATABASE
, вказавши COLLATE
пункт. Це порівняння на рівні бази даних використовується для змінних та рядкових літералів, а також за замовчуванням для нових (та змінених!) Стовпців, коли COLLATE
пункт не вказано (що стосується прикладу коду у питанні).
- Для отримання додаткової інформації про зібрання / кодування / Unicode відвідайте: Інформація про зібрання