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


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.