indeksowanie ciągów znaków bez rozróżniania wielkości liter, ale przypadek danych jest utrwalany. Jak to faktycznie działa?
W rzeczywistości nie jest to zachowanie specyficzne dla SQL Server, to po prostu, jak te rzeczy działają w ogóle.
Dane są więc danymi. Jeśli mówimy konkretnie o indeksie, dane muszą być przechowywane, ponieważ w innym przypadku wymagałoby to każdorazowego sprawdzenia w głównej tabeli, aby uzyskać rzeczywistą wartość, i nie byłoby możliwości zastosowania indeksu obejmującego (w najmniej dla typów ciągów).
Dane, zarówno w indeksie tabel / indeks klastrowy, jak i indeks nieklastrowany, nie zawierają żadnych informacji o sortowaniu / sortowaniu. To po prostu dane. Sortowanie (reguły regionalne / kultura i wrażliwości) to tylko metadane dołączone do kolumny i używane, gdy wywoływana jest operacja sortowania (chyba że zostanie zastąpiona przezCOLLATE
klauzula), która obejmowałaby utworzenie / przebudowę indeksu. Reguły zdefiniowane przez niebinarne zestawienie są używane do generowania kluczy sortowania, które są binarnymi reprezentacjami łańcucha (klucze sortowania nie są potrzebne w zestawieniach binarnych). Te reprezentacje binarne uwzględniają wszystkie reguły regionalne / kulturowe i wybrane wrażliwości. Klawisze sortowania służą do umieszczania rekordów we właściwej kolejności, ale same nie są przechowywane w indeksie lub tabeli. Nie są przechowywane (przynajmniej nie widziałem tych wartości w indeksie i powiedziano mi, że nie są przechowywane), ponieważ:
- Nie są tak naprawdę potrzebne do sortowania, ponieważ i tak byłyby w tej samej kolejności co wiersze w tabeli lub indeksie. Ale fizyczna kolejność indeksu to tylko sortowanie, a nie porównywanie.
- Przechowywanie ich może przyspieszyć porównania , ale zwiększy także indeks, ponieważ minimalny rozmiar pojedynczego znaku wynosi 5 bajtów, a to po prostu „narzut” (struktury klucza sortowania). Większość znaków ma po 2 bajty plus 1 bajt, jeśli występuje akcent, oraz 1 bajt, jeśli jest to duża litera. Na przykład „e” to 7-bajtowy klucz, „E” i „é” to 8 bajtów, a „É” to 9-bajtowy klucz. Dlatego nie warto ich przechowywać na końcu.
Istnieją dwa rodzaje zestawień: SQL Server i Windows.
SQL Server
SQL_
Sortowania SQL Server (te o nazwach rozpoczynających się od ) są starszym sposobem sortowania / porównywania sprzed SQL Server 2000 (choć niestety nadalSQL_Latin1_General_CP1_CI_AS
jest to domyślna instalacja w amerykańskich systemach operacyjnych w języku angielskim). W tym starszym, uproszczonym modelu nieobsługującym kodu Unicode każda kombinacja ustawień regionalnych, strony kodowej i różnych wrażliwości ma statyczne mapowanie każdego ze znaków na tej stronie kodowej. Każdemu znakowi przypisuje się wartość (tj. Wagę sortowania), aby wskazać, jak jest on równy z innymi. Porównania w tym modelu wydają się wykonywać operację dwuprzebiegową:
- Najpierw usuwa wszystkie akcenty (takie, że „ ü ” staje się „ u ”), rozwija znaki takie jak „ Æ ” do „ A ” i „ E ”, a następnie sortuje początkowo, aby słowa były w naturalnej kolejności (jak byś spodziewaj się, że znajdziesz je w słowniku).
- Następnie przechodzi znak po znaku, aby ustalić równość na podstawie tych wartości leżących u podstaw każdego znaku. Ta druga część jest tym, co Mustaccio opisuje w swojej odpowiedzi .
Jedynymi czułościami, które można regulować w tych zestawieniach, są: „wielkość liter” i „akcent” („szerokość”, „typ kana” i „selektor wariacji” nie są dostępne). Ponadto żadne z tych zestawień nie obsługuje znaków uzupełniających (co ma sens, ponieważ są one specyficzne dla Unicode, a te zestawienia dotyczą tylko danych innych niż Unicode).
To podejście dotyczy tylko danych nieobsługujących kodu Unicode VARCHAR
. Każda unikalna kombinacja ustawień regionalnych, strony kodowej, rozróżniania wielkości liter i rozróżniania akcentów ma określony „identyfikator sortowania”, który można zobaczyć w następującym przykładzie:
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
Jedyną różnicą między pierwszymi dwoma zestawieniami jest rozróżnianie wielkości liter. Trzecie sortowanie to sortowanie w systemie Windows, a zatem nie ma statycznej tabeli mapowania.
Ponadto te sortowania powinny być sortowane i porównywane szybciej niż sortowania w systemie Windows, ponieważ są prostymi funkcjami wyszukiwania znaków do sortowania według wagi. Jednak te zestawienia są również znacznie mniej funkcjonalne i należy ich unikać, jeśli to w ogóle możliwe.
Windows
Sortowania w systemie Windows (te o nazwach, które nie zaczynają się od SQL_
) są nowszym (począwszy od SQL Server 2000) sposobem sortowania / porównywania. W tym nowszym, złożonym modelu Unicode każda kombinacja ustawień narodowych, strony kodowej i różnych wrażliwości nie ma przypisania statycznego. Po pierwsze, w tym modelu nie ma stron kodowych. Ten model przypisuje domyślną wartość sortowania do każdego znaku, a następnie każde ustawienie regionalne / kultura może ponownie przypisać wartości sortowania do dowolnej liczby znaków. Pozwala to wielu kulturom używać tych samych znaków na różne sposoby. Ma to wpływ na umożliwienie naturalnego sortowania wielu języków przy użyciu tego samego sortowania, jeśli nie używają one tych samych znaków (i jeśli jeden z nich nie musi ponownie przypisywać żadnych wartości i może po prostu użyć domyślnych).
Wartości sortowania w tym modelu nie są pojedynczymi wartościami. Są to tablice wartości, które przypisują względne wagi do litery podstawowej, wszelkich znaków diakrytycznych (tj. Akcentów), obudowy itp. Jeśli w sortowaniu rozróżniana jest wielkość liter, wówczas używana jest część „wielkość liter” w tej tablicy, w przeciwnym razie zostanie zignorowana stąd niewrażliwy). Jeśli zestawienie jest wrażliwe na akcent, wówczas używana jest „diakrytyczna” część tablicy, w przeciwnym razie jest ignorowana (stąd niewrażliwa).
Porównania w tym modelu są operacją wieloprzebiegową:
- Po pierwsze, łańcuch jest znormalizowany, aby zrównać się różne sposoby reprezentowania tego samego znaku. Na przykład „ ü ” może być pojedynczym znakiem / punktem kodowym (U + 00FC). Możesz także połączyć nieakcentowane „ u ” (U + 0075) z łączną diaeresisą „ ̈ ” (U + 0308), aby uzyskać: „ ü ”, który nie tylko wygląda tak samo po renderowaniu (chyba że występuje problem z twoja czcionka), ale jest również uważany za taki sam jak wersja jednoznakowa (U + 00FC), chyba że używasz sortowania binarnego (który porównuje bajty zamiast znaków). Normalizacja dzieli pojedynczy znak na różne części, w tym rozszerzenia dla znaków takich jak „ Æ ” (jak wspomniano powyżej dla zestawień SQL Server).
- Operacja porównania w tym modelu przebiega znak po znaku na każdą czułość . Klucze sortowania dla łańcuchów są określane przez zastosowanie odpowiednich elementów tablicy sortowania wartości każdego znaku, na podstawie której „wrażliwość” jest wrażliwa. Kluczowe wartości sortowania są uporządkowane według wszystkich pierwotnych wartości czułości każdego znaku (znak podstawowy), po których następują wszystkie wartości dodatkowej czułości (waga diakrytyczna), a następnie waga wielkości liter każdego znaku i tak dalej.
- Sortowanie odbywa się na podstawie obliczonych kluczy sortowania. Przy każdej pogrupowanej czułości można uzyskać inną kolejność sortowania niż w przypadku równoważnego sortowania programu SQL Server podczas porównywania ciągów wielu znaków i zaangażowanych akcentów, a sortowanie jest wrażliwe na akcent (a tym bardziej, jeśli zestawienie jest rozróżniana jest również wielkość liter).
Aby uzyskać więcej informacji na temat tego sortowania, ostatecznie opublikuję post, który pokazuje kluczowe wartości sortowania, sposób ich obliczania, różnice między SQL Server i zestawieniami Windows itp. Ale na razie zapoznaj się z moją odpowiedzią na: Sortowanie wrażliwe na akcent ( należy pamiętać, że inna odpowiedź na to pytanie jest dobrym wyjaśnieniem oficjalnego algorytmu Unicode, ale zamiast tego SQL Server używa niestandardowego, choć podobnego algorytmu, a nawet niestandardowej tabeli wag).
Wszystkie wrażliwości można dostosować w tych zestawieniach: „wielkość liter”, „akcent”, „szerokość”, „typ kana” i „selektor wariacji” (począwszy od SQL Server 2017 i tylko dla zestawień japońskich). Ponadto niektóre z tych zestawień (gdy są używane z danymi Unicode) obsługują dodatkowe znaki (począwszy od SQL Server 2012). To podejście dotyczy zarówno danych, jak NVARCHAR
i VARCHAR
danych (nawet danych nieobsługujących kodu Unicode). Ma zastosowanie do VARCHAR
danych nieobsługujących kodu Unicode , najpierw konwertując wewnętrznie wartość na Unicode, a następnie stosując reguły sortowania / porównywania.
Proszę zanotować:
- Nie ma uniwersalnego domyślnego sortowania dla programu SQL Server. Domyślne ustawienie instalacji różni się w zależności od bieżących ustawień regionalnych / językowych systemu operacyjnego w chwili instalacji (co niestety
SQL_Latin1_General_CP1_CI_AS
dotyczy systemów w języku angielskim w USA, więc proszę głosować na tę sugestię ). Można to zmienić podczas instalacji. To sortowanie na poziomie instancji ustawia następnie sortowanie dla [model]
bazy danych, która jest szablonem używanym podczas tworzenia nowych baz danych, ale sortowanie można zmienić podczas wykonywania CREATE DATABASE
, określając COLLATE
klauzulę. To sortowanie na poziomie bazy danych jest używane w przypadku literałów zmiennych i literałów, a także domyślnych dla nowych (i zmienionych!) Kolumn, gdy COLLATE
klauzula nie jest określona (tak jest w przypadku przykładowego kodu w pytaniu).
- Aby uzyskać więcej informacji na temat zestawień / kodowań / Unicode, odwiedź: Informacje o zestawieniach