Przede wszystkim przepraszam za tak długą odpowiedź, ponieważ uważam, że nadal istnieje wiele zamieszania, gdy ludzie mówią o terminach takich jak sortowanie, porządek sortowania, strona kodowa itp.
Z BOL :
Sortowania w SQL Server zapewniają reguły sortowania, wielkość liter i właściwości czułości akcentu dla danych . Zestawienia używane z typami danych znakowych, takimi jak char i varchar, określają stronę kodową i odpowiadające znaki, które mogą być reprezentowane dla tego typu danych. Niezależnie od tego, czy instalujesz nową instancję programu SQL Server, przywracasz kopię zapasową bazy danych, czy łączysz serwer z bazami danych klientów, ważne jest, aby zrozumieć wymagania regionalne, kolejność sortowania oraz wrażliwość na wielkość liter i liter, z którymi będziesz pracować .
Oznacza to, że sortowanie jest bardzo ważne, ponieważ określa zasady sortowania i porównywania ciągów znaków danych.
Uwaga: Więcej informacji na temat COLLATIONPROPERTY
Teraz Najpierw zrozummy różnice ......
Uruchamianie poniżej T-SQL:
SELECT *
FROM::fn_helpcollations()
WHERE NAME IN (
'SQL_Latin1_General_CP1_CI_AS'
,'Latin1_General_CI_AS'
)
GO
SELECT 'SQL_Latin1_General_CP1_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'Version') AS 'Version'
UNION ALL
SELECT 'Latin1_General_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'Version') AS 'Version'
GO
Wyniki byłyby następujące:
Patrząc na powyższe wyniki, jedyną różnicą jest kolejność sortowania między 2 zestawieniami, ale to nieprawda, co możesz zobaczyć, jak poniżej:
Test 1:
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('Kin_Tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('Kin_Tester1')
--Now try to join both tables
SELECT *
FROM Table_Latin1_General_CI_AS LG
INNER JOIN Table_SQL_Latin1_General_CP1_CI_AS SLG ON LG.Comments = SLG.Comments
GO
Wyniki testu 1:
Msg 468, Level 16, State 9, Line 35
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.
Z powyższych wyników widzimy, że nie możemy bezpośrednio porównywać wartości w kolumnach z różnymi zestawieniami, musisz użyć COLLATE
do porównania wartości kolumn.
TEST 2:
Główną różnicą jest wydajność, jak wskazuje Erland Sommarskog w tej dyskusji na msdn .
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_tester1')
--- Utwórz indeksy na obu tabelach
CREATE INDEX IX_LG_Comments ON Table_Latin1_General_CI_AS(Comments)
go
CREATE INDEX IX_SLG_Comments ON Table_SQL_Latin1_General_CP1_CI_AS(Comments)
--- Uruchom zapytania
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
--- Będzie to miało konwersję IMPLICIT
--- Uruchom zapytania
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
--- NIE będzie to miało IMPLICIT Conversion
Powodem niejawnej konwersji jest to, że mam sortowanie bazy danych i serwera zarówno jako, jak SQL_Latin1_General_CP1_CI_AS
i tabela Table_Latin1_General_CI_AS ma kolumnę Komentarze zdefiniowane jak w VARCHAR(50)
przypadku COLLATE Latin1_General_CI_AS , więc podczas wyszukiwania SQL Server musi wykonać konwersję IMPLICIT.
Test 3:
Przy takim samym ustawieniu porównamy teraz kolumny varchar z wartościami nvarchar, aby zobaczyć zmiany w planach wykonania.
- uruchom zapytanie
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
- uruchom zapytanie
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
Zauważ, że pierwsze zapytanie jest w stanie wykonać wyszukiwanie indeksu, ale musi wykonać niejawną konwersję, podczas gdy drugie wykonuje skanowanie indeksu, które okazuje się nieefektywne pod względem wydajności podczas skanowania dużych tabel.
Wniosek:
- Wszystkie powyższe testy pokazują, że prawidłowe sortowanie jest bardzo ważne dla instancji serwera bazy danych.
SQL_Latin1_General_CP1_CI_AS
to zestawienie SQL z regułami, które pozwalają na sortowanie danych dla kodu Unicode i innego niż Unicode.
- Sortowanie SQL nie będzie w stanie używać indeksu podczas porównywania danych Unicode i innych niż Unicode, jak widać w powyższych testach, że porównując dane nvarchar z danymi varchar, skanuje indeks i nie szuka.
Latin1_General_CI_AS
to zestawienie systemu Windows z regułami, które pozwalają ci sortować dane dla Unicode i nie Unicode są takie same.
- System Windows może nadal korzystać z indeksu (wyszukiwanie indeksu w powyższym przykładzie) podczas porównywania danych unicode i innych niż unicode, ale widzisz niewielki spadek wydajności.
- Gorąco polecam przeczytanie odpowiedzi Erlanda Sommarskoga + elementy, na które wskazał.
Pozwoli mi to nie mieć problemów ze stołami #temp, ale czy są jakieś pułapki?
Zobacz moją odpowiedź powyżej.
Czy straciłbym jakąkolwiek funkcjonalność lub funkcje, nie używając „aktualnego” zestawienia SQL 2008?
Wszystko zależy od tego, do jakiej funkcjonalności / funkcji się odnosisz. Sortowanie to przechowywanie i sortowanie danych.
A co, kiedy przeprowadzimy się (np. Za 2 lata) z 2008 do SQL 2012? Czy wtedy będę miał problemy? Czy w pewnym momencie byłbym zmuszony przejść do Latin1_General_CI_AS?
Nie mogę ręczyć! Ponieważ wszystko może się zmienić i zawsze dobrze jest być zgodnym z sugestią Microsoftu +, musisz zrozumieć swoje dane i pułapki, o których wspomniałem powyżej. Zapoznaj się także z tym i tymi elementami łączenia.
Przeczytałem, że niektóre skrypty DBA uzupełniają rzędy kompletnych baz danych, a następnie uruchom skrypt wstawiania do bazy danych z nowym zestawieniem - jestem bardzo przestraszony i nieufny - czy poleciłbyś to zrobić?
Jeśli chcesz zmienić sortowanie, przydatne są takie skrypty. Przekonałem się, że wiele razy zmieniam układanie baz danych, aby dopasować układanie na serwerze i mam kilka skryptów, które robią to całkiem nieźle. Daj mi znać, jeśli będziesz tego potrzebować.
Bibliografia :