우선, 사람들이 데이터 정렬, 정렬 순서, 코드 페이지 등과 같은 용어에 대해 이야기 할 때 여전히 많은 혼란이 있다고 느끼기 때문에 그러한 긴 대답에 대해 사과드립니다.
에서 BOL :
SQL Server의 데이터 정렬은 데이터의 정렬 규칙, 대 / 소문자 구분 속성을 제공합니다 . char 및 varchar와 같은 문자 데이터 형식과 함께 사용되는 데이터 정렬은 코드 페이지와 해당 데이터 형식으로 나타낼 수있는 해당 문자를 나타냅니다. 새 SQL Server 인스턴스를 설치하거나 데이터베이스 백업을 복원하거나 서버를 클라이언트 데이터베이스에 연결하는 경우 작업 할 데이터의 로캘 요구 사항, 정렬 순서 및 대 / 소문자를 이해하는 것이 중요합니다. .
즉, 데이터 정렬이 데이터의 문자열을 정렬하고 비교하는 방법에 대한 규칙을 지정하므로 데이터 정렬이 매우 중요합니다.
참고 : COLLATIONPROPERTY에 대한 추가 정보
이제 차이점을 먼저 이해합시다 ......
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
결과는 다음과 같습니다.
위의 결과를 보면 유일한 차이점은 두 데이터 정렬 간의 정렬 순서입니다. 그러나 사실이 아니므로 다음과 같은 이유를 알 수 있습니다.
시험 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
시험 결과 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.
위의 결과에서 우리는 다른 데이터 정렬을 가진 열의 값을 직접 비교할 수 없으므로 COLLATE
열 값을 비교하는 데 사용해야한다는 것을 알 수 있습니다 .
테스트 2 :
Erland Sommarskog 가 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')
--- 두 테이블 모두에서 인덱스 생성
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)
--- 쿼리를 실행
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
--- 이것은 묵시적 변환이있을 것입니다
--- 쿼리를 실행
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
--- 이것은 절대 변환 이 없습니다
나는 같이 모두 내 데이터베이스 및 서버 데이터 정렬을 가지고 있기 때문에 암시 적 변환을위한 이유는 SQL_Latin1_General_CP1_CI_AS
테이블의 Table_Latin1_General_CI_AS가 열이 댓글 로 정의 VARCHAR(50)
와 COLLATE Latin1_General_CI_AS을 너무 SQL 서버는 암시 적 변환을 할 수있는 조회 중.
시험 3 :
동일한 설정으로 varchar 열과 nvarchar 값을 비교하여 실행 계획의 변경 사항을 확인합니다.
-쿼리를 실행
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
-쿼리를 실행
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
첫 번째 쿼리는 인덱스 검색을 수행 할 수 있지만 암시 적 변환을 수행해야하는 반면 두 번째 쿼리는 큰 테이블을 검색 할 때 성능 측면에서 비효율적 인 것으로 인덱스 검색을 수행합니다.
결론 :
- 위의 모든 테스트에 따르면 데이터베이스 서버 인스턴스에 올바른 데이터 정렬이 매우 중요합니다.
SQL_Latin1_General_CP1_CI_AS
유니 코드와 비 유니 코드에 대한 데이터를 정렬 할 수있게하는 규칙이있는 SQL 데이터 정렬입니다.
- nvarchar 데이터와 varchar 데이터를 비교할 때 인덱스 스캔을 수행하고 검색하지 않는 위의 테스트에서 볼 수 있듯이 유니 코드와 비 유니 코드 데이터를 비교할 때 SQL 데이터 정렬은 인덱스를 사용할 수 없습니다.
Latin1_General_CI_AS
유니 코드와 비 유니 코드에 대한 데이터를 정렬 할 수 있도록하는 규칙이 포함 된 Windows 데이터 정렬입니다.
- 유니 코드 데이터와 비 유니 코드 데이터를 비교할 때 Windows 데이터 정렬은 여전히 인덱스 (위 예제에서 인덱스 검색)를 사용할 수 있지만 약간의 성능 저하가 있습니다.
- Erland Sommarskog 답변 + 그가 지적한 연결 항목을 읽는 것이 좋습니다.
이렇게하면 #temp 테이블에 문제가 없지만 함정이 있습니까?
위의 답변을 참조하십시오.
SQL 2008의 "현재"데이터 정렬을 사용하지 않으면 어떤 종류의 기능도 손실됩니까?
그것은 당신이 말하는 기능 / 기능에 달려 있습니다. 데이터 정렬은 데이터를 저장하고 정렬합니다.
2008 년에서 SQL 2012로 이전 할 때 (예 : 2 년)는 어떻습니까? 그렇다면 문제가 있습니까? 어느 시점에서 Latin1_General_CI_AS로 가야합니까?
캔트 바우처! 상황이 바뀔 수 있고 항상 Microsoft의 제안과 일치하는 것이 좋으므로 + 위에서 언급 한 데이터와 함정을 이해해야합니다. 또한 참조 이 와 이 연결 항목.
일부 DBA의 스크립트가 완전한 데이터베이스의 행을 완성한 다음 새 데이터 정렬을 사용하여 데이터베이스에 삽입 스크립트를 실행한다는 것을 읽었습니다.
데이터 정렬을 변경하려는 경우 이러한 스크립트가 유용합니다. 서버 데이터 정렬과 여러 번 일치하도록 데이터베이스 데이터 정렬을 변경하는 것을 발견했으며 꽤 깔끔한 스크립트가 있습니다. 필요한 경우 알려주세요.
참고 문헌 :