대소 문자를 구분하지 않는 데이터 정렬은 어떻게 작동합니까?


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'

SQL Server 데이터 정렬에 대한 질문 Robert Sheldon의 질문너무 부끄럽습니다 . 데이터 정렬 사용 방법에 대해 설명합니다. 데이터 정렬 작동 방식은 다루지 않습니다. 사례 데이터를 저장하면서 동시에 사례를 신경 쓰지 않고 인덱스를 효율적으로 생성 / 조회하는 방법에 관심이 있습니다.


1
대소 문자를 구분하는 필드에 대해 대소 문자를 구분하지 않는 문자열을 효율적으로 쿼리 (예 : 색인 검색 사용) 할 수 있지만 약간 성가신 일 입니다.
John Eisbrener

cocogorilla : 방금 답변의 끝에 "기본"데이터 정렬 추가 한 메모 # 1을 참조하십시오.
Solomon Rutzky

답변:


26

대소 문자를 구분하지 않는 문자열에 대해 인덱싱하지만 데이터의 경우는 유지됩니다. 실제로 어떻게 작동합니까?

이것은 실제로 SQL Server 특정 동작이 아니며 일반적인 방식으로 작동하는 방식입니다.

따라서 데이터는 데이터입니다. 인덱스에 대해 구체적으로 말하면 데이터 를 그대로 저장 해야 합니다. 그렇지 않으면 실제 값을 얻기 위해 매번 기본 테이블을 조회해야하며 커버링 인덱스가 발생할 가능성이 없습니다. 문자열 유형에는 적합하지 않음).

테이블 / 클러스터형 인덱스 또는 비 클러스터형 인덱스의 데이터에 데이터 정렬 / 정렬 정보 가 없습니다 . 단순히 데이터입니다. 데이터 정렬 (로캘 / 문화 규칙 및 민감도)은 열에 첨부 된 메타 데이터 일 뿐이며 정렬 작업이 호출 될 때 사용됩니다 (COLLATE절)-색인 생성 / 재 구축이 포함됩니다. 이진이 아닌 데이터 정렬로 정의 된 규칙은 문자열의 이진 표현 인 정렬 키를 생성하는 데 사용됩니다 (이진 데이터 정렬에는 정렬 키가 필요하지 않음). 이러한 이진 표현은 모든 로캘 / 문화 규칙과 선택된 감도를 통합합니다. 정렬 키는 레코드를 올바른 순서로 배치하는 데 사용되지만 인덱스 나 테이블에는 저장되지 않습니다. 그들은 다음과 같은 이유로 저장되지 않습니다 (적어도 색인에서 이러한 값을 보지 못했고 저장되지 않았다는 말을 들었습니다).

  1. 어쨌든 테이블이나 인덱스의 행과 동일한 순서 일뿐이므로 정렬에 실제로 필요하지 않습니다 . 그러나 인덱스의 물리적 순서는 비교가 아니라 정렬입니다.
  2. 그것들을 저장하면 비교가 빨라질 수 있지만 , 단일 문자의 최소 크기가 5 바이트이고 정렬 키 구조의 "오버 헤드"일 뿐이므로 인덱스가 더 커집니다. 대부분의 문자는 각각 2 바이트이며 악센트가있는 경우 1 바이트이며 대문자이면 1 바이트입니다. 예를 들어 "e"는 7 바이트 키이고 "E"와 "é"는 8 바이트이며 "É"는 9 바이트 키입니다. 따라서 결국 이들을 저장할 가치가 없습니다.

데이터 정렬에는 SQL Server와 Windows의 두 가지 유형이 있습니다.

SQL 서버

SQL 서버 데이터 정렬 (로 시작하는 이름을 가진 사람이 SQL_) 비교 / 정렬의 이전, 사전 SQL Server 2000의 방법이다 (비록 SQL_Latin1_General_CP1_CI_AS입니다 여전히 매우 슬프게도, 미국 영어 운영체제의 설치 기본값). 이 이전의 단순하고 유니 코드가 아닌 모델에서 로케일, 코드 페이지 및 다양한 감도의 각 조합에는 해당 코드 페이지의 각 문자에 대한 정적 맵핑이 제공됩니다. 각 문자에는 다른 문자와 동일한 방식을 나타내는 값 (즉, 정렬 가중치)이 할당됩니다. 이 모델의 비교는 두 단계로 진행되는 것으로 보입니다.

  1. 먼저 모든 악센트를 제거하고 ( "  ü  "가 "  u  "가 됨) " Æ  " 와 같은 문자  를 "  A  "와 "  E  "로 확장 한 다음 단어가 자연스럽게 정렬되도록 초기 정렬을 수행합니다 (어떻게 하는가? 사전에서 찾을 것으로 예상).
  2. 다음에, 간다 문자로 문자를 각 문자 당이 기본 값을 기준으로 평등을 확인합니다. 이 두 번째 부분은 mustaccio가 그의 답변 에서 설명하는 입니다.

이러한 데이터 정렬에서 조정할 수있는 유일한 감도는 "case"및 "accent"입니다 ( "width", "kana type"및 "variation selector"는 사용할 수 없음). 또한 이러한 데이터 정렬은 보충 문자를 지원하지 않습니다 (유니 코드에 따라 다르며 유니 코드가 아닌 데이터에만 적용됩니다).

이 방법 은 비 유니 코드 데이터 에만 적용 됩니다VARCHAR . 로케일, 코드 페이지, 대소 문자 구분 및 악센트 구분의 고유 한 각 조합에는 다음과 같은 예에서 볼 수있는 특정 "정렬 ID"가 있습니다.

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 데이터 정렬 SQL_은 SQL Server 2000에서 시작하는 새로운 정렬 / 비교 방법입니다. 이 새롭고 복잡한 유니 코드 모델에서는 각 로캘, 코드 페이지 및 다양한 민감도에 정적 매핑 이 제공 되지 않습니다 . 우선이 모델에는 코드 페이지가 없습니다. 이 모델은 각 문자에 기본 정렬 값을 할당 한 다음 각 로캘 / 문화는 정렬 값을 여러 문자에 다시 할당 할 수 있습니다. 이를 통해 여러 문화권에서 다른 방식으로 동일한 문자를 사용할 수 있습니다. 이는 동일한 문자를 사용하지 않는 경우 (및 그 중 하나가 값을 다시 할당 할 필요가없고 단순히 기본값을 사용할 수있는 경우) 동일한 데이터 정렬을 사용하여 여러 언어를 자연스럽게 정렬하는 데 영향을줍니다.

이 모델의 정렬 값은 단일 값이 아닙니다. 기본 문자, 분음 부호 (예 : 악센트), 대소 문자 등에 상대적 가중치를 할당하는 값의 배열입니다. 데이터 정렬이 대소 문자를 구분하면 해당 배열의 "case"부분이 사용됩니다. 그렇지 않으면 무시됩니다 ( 따라서 둔감하다). 데이터 정렬이 악센트를 구분하면 배열의 "분음 부호"부분이 사용되며 그렇지 않으면 무시됩니다 (따라서 둔감합니다).

이 모델의 비교는 다중 패스 작업입니다.

  1. 첫째, 문자열은 정규화되어 동일한 문자를 나타내는 다양한 방법이 동일합니다. 예를 들어 " ü "는 단일 문자 / 코드 포인트 (U + 00FC) 일 수 있습니다. 또한 비 악센트 "결합 할 수있는 U 합성 분음"로 "(U + 0075)를 ̈ 얻기 위해"(0308 U +) : " ü을 "뿐만 아니라 보이는 같은 렌더링 할 때 (문제와 함께가 아니라면 이진 데이터 정렬 (문자 대신 바이트 비교)을 사용하지 않는 한 단일 문자 버전 (U + 00FC)과 동일한 것으로 간주됩니다. 정규화는 단일 문자를 다양한 조각으로 나눕니다. 여기에는 " Æ  " 와 같은 문자의 확장이 포함됩니다  (SQL Server 데이터 정렬에 대해 위에서 언급 한 것처럼).
  2. 이 모델의 비교 연산은 각 감도마다 문자 별로 진행 됩니다 . 문자열의 정렬 키는 "민감한"감도를 기준으로 각 문자 데이터 정렬 배열 값의 적절한 요소를 적용하여 결정됩니다. 정렬 키 값은 각 문자 (기본 문자)의 모든 기본 감도, 모든 보조 민감도 (분음 가중치), 각 문자의 대소 문자 가중치 등으로 정렬됩니다.
  3. 정렬은 계산 된 정렬 키를 기준으로 수행됩니다. 각 민감도를 그룹화하면 여러 문자의 문자열을 비교할 때 동등한 SQL Server 데이터 정렬 에서와는 다른 정렬 순서를 얻을 수 있으며 악센트가 포함되고 데이터 정렬은 악센트에 민감합니다 (그리고 데이터 정렬이 대소 문자 구분).

이 정렬에 대한 자세한 내용은 정렬 키 값, 계산 방법, SQL Server와 Windows 데이터 정렬의 차이점 등을 보여주는 게시물을 게시 할 예정입니다. 그러나 지금은 내 대답 : Accent Sensitive Sort ( 이 질문에 대한 다른 대답은 공식 유니 코드 알고리즘에 대한 좋은 설명이지만 SQL Server는 비슷한 알고리즘이지만 사용자 정의 가중치 테이블을 사용하지만 대신 사용자 정의를 사용합니다).

모든 대소 문자 구분은 "case", "accent", "width", "kana type"및 "variation selector"(SQL Server 2017에서 시작하여 일본어 데이터 정렬에만 해당) 데이터 정렬에서 조정할 수 있습니다. 또한 이러한 데이터 정렬 중 일부 (유니 코드 데이터와 함께 사용하는 경우)는 보조 문자 (SQL Server 2012에서 시작)를 지원합니다. 이 방법은 데이터 NVARCHAR VARCHAR 유니 코드가 아닌 데이터에도 적용됩니다 . VARCHAR먼저 내부적으로 값을 유니 코드로 변환 한 다음 정렬 / 비교 규칙을 적용하여 비 유니 코드 데이터에 적용됩니다.


참고 사항 :

  1. SQL Server에 대한 범용 기본 데이터 정렬이 없습니다. 설치시 OS의 현재 로케일 / 언어 설정에 따라 다른 설치 기본값이 있습니다 (불행히 SQL_Latin1_General_CP1_CI_AS미국 영어 시스템에서는 이 제안에 투표하십시오 ). 설치 중에 변경할 수 있습니다. 그런 다음이 인스턴스 레벨 데이터 정렬 [model]은 새 DB를 생성 할 때 사용되는 템플릿 인 DB 의 데이터 정렬을 설정 하지만 절 CREATE DATABASE을 지정하여 실행할 때 데이터 정렬을 변경할 수 있습니다 COLLATE. 이 데이터베이스 수준 데이터 정렬은 변수 및 문자열 리터럴뿐만 아니라 COLLATE절이 지정되지 않은 경우 새 (및 변경된!) 열의 기본값에 사용 됩니다 (문제의 예제 코드의 경우).
  2. 데이터 정렬 / 인코딩 / 유니 코드에 대한 자세한 내용을 보려면 다음을 방문하십시오. 데이터 정렬 정보

5

일반적으로 각 문자에 특정 점수를 할당하는 데이터 정렬 테이블을 사용하여 구현됩니다. 정렬 루틴에는 데이터 정렬 스코어를 사용하여 문자열을 문자별로 비교하기 위해 기본 또는 명시 적으로 지정된 적절한 테이블을 사용하는 비교기가 있습니다. 예를 들어, 특정 데이터 정렬 테이블이 1의 점수를 "a"에, 201을 "A"에 할당하고이 특정 구현에서 낮은 점수가 높은 우선 순위를 의미하는 경우 "a"는 "A"보다 먼저 정렬됩니다. 다른 테이블은 역 점수를 지정할 수 있습니다 : 201에서 "a"로, 1에서 "A"로 정렬 순서가 역순으로됩니다. 또 다른 테이블은 "a", "A", "Á"및 "Å"에 동일한 점수를 할당하여 대소 문자를 구분하지 않고 비교 및 ​​정렬 할 수 있습니다.

마찬가지로, 이러한 조합 테이블 기반 비교기는 인덱스 키를 술어에 제공된 값과 비교할 때 사용됩니다.


1
참고로,이 정보는 데이터에 SQL_사용될 때 SQL Server 데이터 정렬 (즉, 이름이로 시작하는 데이터 정렬)을 사용하는 관점에서만 정확 VARCHAR합니다. Windows 데이터 정렬을 사용할 때 (이름 이로 시작 하지 않음 ) NVARCHAR데이터 또는 VARCHAR데이터에 대해서는 사실이 아닙니다 . SQL_
솔로몬 루츠 키
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.