국제 데이터베이스에 대한 데이터 정렬을 선택하는 방법은 무엇입니까?


22

내가 쿼리의 결과를 표시하는 가장 좋은 방법을 생각하므로, (UTF-8을 사용하는) 다른 언어로 데이터를 저장하는 데이터베이스를 설계하고있어 (쿼리 자체 동안 사용자의 언어에 따라 주문되는 하나 이상이 있기 때문에 다음과 같이 올바른 방법으로 ) :

SELECT a < b COLLATE "de_DE" FROM test1;

이것이 국제 데이터를 처리하는 올바른 방법이라고 가정하면 데이터베이스 자체에 가장 적합한 데이터 정렬은 무엇입니까? PostgreSQL 설명서는 다음과 같이 말합니다 .

C 및 POSIX 데이터 정렬은 모두 "전통적인 C"동작을 지정합니다. 여기서 "A"부터 "Z"까지의 ASCII 문자 만 문자로 취급되며 정렬은 문자 코드 바이트 값으로 엄격하게 수행됩니다.

이 경우에 이것이 최선의 선택이라고 생각합니까, 아니면 제가 틀렸습니까?

(보너스 질문 : 쿼리 자체에서 데이터 정렬을 선택하는 것이 너무 느립니까?).


2
가장 큰 어려움은 다국어 DB에서는 배열 가능한 텍스트의 인덱스가 데이터 정렬에 따라 많은 인덱스가 필요하다는 것입니다. 그러나 부분 데이터 정렬 / 언어 내에서만 검색하려는 경우 부분 인덱스를 사용하여 인덱스 크기를 제어 할 수 있습니다.
Craig Ringer

2
소스를 인용 할 때 링크를 추가하십시오.
Erwin Brandstetter

답변:


27

C조합은 최적의 선택이 될 것입니다.

로케일이 없으면 모든 것이 조금 더 빠릅니다. 데이터 정렬 잘 어쨌든 없기 때문에 그리고, 데이터베이스를 생성 하지 않고 함께 의미 정렬 C.

많은 작업에 데이터 정렬을 제공해야하는 것은 고통 스러울 수 있습니다. 그러나 기본 데이터 정렬과 임시 데이터 정렬간에 속도에 눈에 띄는 차이가 없어야합니다. 결국 그것은 정렬되지 않은 데이터 일 뿐이며 정렬 할 때 데이터 정렬 규칙이 적용됩니다.

Postgres는 기본 OS에서 제공하는 로케일 설정을 기반으로하므로 사용할 로케일마다 로케일을 생성해야합니다. 여기여기 에 대한 관련 답변이 더 있습니다 .

그러나 @Craig에서 이미 언급했듯이이 시나리오 에서는 인덱스 가 병목 현상입니다. 인덱스 데이터 정렬은 문자 데이터와 관련된 많은 경우 적용된 연산자의 데이터 정렬과 일치해야합니다.

COLLATE인덱스 에서 지정자를 사용하여 일치하는 인덱스를 생성 할 수 있습니다 . 동일한 테이블에서 데이터를 혼합하는 경우 부분 인덱스 가 가장 적합합니다.

예를 들어 국제 문자열이있는 테이블은 다음과 같습니다.

CREATE TABLE string (
   string_id serial
  ,lang_id   int NOT NULL
  ,string    text NOT NULL
);

그리고 한 번에 한 언어에 관심이 있습니다.

SELECT *
FROM   string
WHERE  lang_id = 5  -- 5 being German / Germany here
AND    string > 'foo' COLLATE "de_DE"
ORDER  BY string COLLATE "de_DE";

그런 다음 다음과 같은 부분 색인을 작성하십시오.

CREATE INDEX string_string_lang_id_idx ON string (string COLLATE "de_DE")
WHERE lang_id = 5;

필요한 각 언어마다 하나씩.

실제로 상속 은 이와 같은 테이블에 대한 우수한 접근 방법 일 수 있습니다. 그런 다음 단일 로캘에 대한 문자열 만 포함하는 상속 된 각 테이블에 일반 인덱스를 가질 수 있습니다. 물론 상속 된 테이블에 대한 특수 규칙에 익숙해야합니다.


1
새 데이터베이스에 대해 기본적으로 C 로캘 (또는 정확하지 않은 '비 로캘')을 사용합니까?
Jack Douglas

1
@ JackDouglas : 아니요, 특별한 경우에만 그렇게 할 것입니다. 일반적으로 그 장소에서 일반적으로 사용되는 로케일로 작업하는 것이 훨씬 더 실용적입니다.
Erwin Brandstetter

13

기본 유니 코드 순서를 제공하는 데이터 정렬을 선택하는 것이 좋습니다. 이렇게하면 각 쿼리에서 데이터 정렬을 재정의하지 않아도 결과가 정확하지 않습니다. 불행히도, 대부분의 (모든?) 운영 체제는 단순히 "기본 유니 코드"또는 이와 유사한 이름의 로캘을 제공하지 않으므로 올바른 선택을 추측하거나 연구해야합니다. 예를 들어 Linux / glibc에서 de_DE.utf8 또는 en_US.utf8 로켈은 단순히 기본 동작을 통과하므로 둘 다 좋은 선택입니다.

C 로캘을 사용하는 것이 좋은 생각은 아닙니다. 응용 프로그램의 기본 동작이 쓸모 없기 때문입니다. 또한 사례 변환 작업에서 올바른 동작을 얻지 못할 수 있습니다.

쿼리에서 데이터 정렬을 재정의하면 오버 헤드가 많지 않습니다. 구문 분석 시간 작업 일뿐입니다.


제정신이 아닌 채무 불이행으로 아마 고통이 덜 ..
Erwin Brandstetter

1
현재 테스트 데이터베이스에서 es_CL.utf8을 사용하고 있지만 귀하의 답변 덕분에 조금 더 보았고 utf8_unicode_ci그 길을 찾았습니다 .
Tae

0

도커 컨테이너에서 postgres를 사용하므로 항상 ICU를 사용할 수 있으며 und-x-icu기본값으로 사용 합니다.

이것은 23.2.2.2.2 장에 언급되어있다 . postres 문서에 대한 ICU 데이터 정렬 은 다음과 같습니다.

und-x-icu ( "정의되지 않은")
ICU "루트"데이터 정렬. 언어에 관계없이 합리적인 정렬 순서를 얻으려면 이것을 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.