Jak wybrać zestawienie dla międzynarodowej bazy danych?


22

Projektuję bazę danych, która będzie przechowywać dane w różnych językach (przy użyciu UTF-8), więc myślę, że najlepszym sposobem wyświetlania wyników zapytania jest uporządkowanie go zgodnie z językiem użytkownika podczas samego zapytania ( ponieważ istnieje więcej niż jeden poprawne sposoby ), w następujący sposób:

SELECT a < b COLLATE "de_DE" FROM test1;

Zakładając, że jest to właściwy sposób pracy z danymi międzynarodowymi, który jest najlepszym zestawieniem dla samej bazy danych? Dokumentacja PostgreSQL mówi :

Oba zestawienia C i POSIX określają „tradycyjne zachowanie C”, w którym tylko litery ASCII od „A” do „Z” są traktowane jak litery, a sortowanie odbywa się ściśle według wartości bajtów kodu znaków.

Myślę, że to najlepszy wybór w tym przypadku, czy się mylę?

(Pytanie dodatkowe: czy wybranie sortowania w samym zapytaniu jest zbyt wolne?).


2
Największym problemem, na który będziesz cierpieć, jest to, że w wielojęzycznej bazie danych potrzebujesz wielu indeksów, ponieważ indeksy tekstu zestawialnego są specyficzne dla sortowania. Jeśli jednak masz tendencję do wyszukiwania tylko w ramach częściowego sortowania / języka, możesz użyć indeksów częściowych, aby pomóc utrzymać rozmiar indeksu pod kontrolą.
Craig Ringer

2
Cytując źródło, dodaj link.
Erwin Brandstetter,

Odpowiedzi:


27

CSortowania jest właściwym wyborem.

Wszystko jest trochę szybsze bez ustawień regionalnych. A ponieważ żadne sortowanie i tak nie jest prawidłowe, utwórz bazę danych bez sortowania, co oznacza za pomocą C.

Konieczne może być zestawienie wielu operacji. Jednak nie powinno być zauważalnej różnicy prędkości między zestawieniem domyślnym a zestawieniem ad-hoc. W końcu to tylko nieposortowane dane, a zasady sortowania są stosowane podczas sortowania.

Należy pamiętać, że Postgres opiera się na ustawieniach regionalnych dostarczonych przez podstawowy system operacyjny, dlatego należy wygenerować ustawienia narodowe dla każdego używanego ustawienia narodowego. Więcej w powiązanej odpowiedzi na temat SO tutaj i tutaj .

Jednak, jak już wspomniano @Craig , indeksy stanowią wąskie gardło w tym scenariuszu. Sortowanie indeksu musi odpowiadać sortowaniu zastosowanego operatora w wielu przypadkach, które dotyczą danych znakowych.

Możesz użyć COLLATEspecyfikatora w indeksach, aby utworzyć pasujące indeksy. Indeksy częściowe mogą być idealnym wyborem, jeśli miksujesz dane w tej samej tabeli.

Na przykład tabela z ciągami międzynarodowymi:

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

I najbardziej interesuje Cię jeden język naraz:

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

Następnie utwórz częściowe indeksy, takie jak:

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

Jeden dla każdego języka, którego potrzebujesz.

W rzeczywistości dziedziczenie może być lepszym podejściem dla takiej tabeli. Następnie możesz mieć zwykły indeks na każdej odziedziczonej tabeli zawierający tylko ciągi znaków dla jednego ustawienia narodowego. Oczywiście musisz czuć się komfortowo dzięki specjalnym zasadom dotyczącym odziedziczonych tabel.


1
Czy domyślnie używasz ustawień regionalnych C (a dokładniej „non locale”) dla każdej nowej bazy danych?
Jack Douglas,

1
@JackDouglas: Nie, zrobiłbym to tylko w szczególnych przypadkach. Zazwyczaj bardziej praktyczna jest praca z ogólnie używanymi ustawieniami lokalnymi w tym miejscu.
Erwin Brandstetter,

13

Sugeruję wybranie sortowania zapewniającego domyślne porządkowanie w Unicode. W ten sposób uzyskasz rozsądne wyniki, nawet jeśli nie zastąpisz sortowania w każdym zapytaniu. Niestety, większość (wszystkich?) Systemów operacyjnych nie udostępnia ustawień narodowych, które są po prostu nazywane „domyślnym Unicode” lub czymś podobnym, więc będziesz musiał zgadywać i / lub szukać dobrego wyboru. Na przykład w systemie Linux / glibc ustawienia regionalne de_DE.utf8 lub en_US.utf8 po prostu przechodzą przez domyślne zachowanie, więc oba są dobrym wyborem.

Nie sądzę, aby używanie ustawień regionalnych C było dobrym pomysłem, ponieważ wtedy domyślne zachowanie aplikacji będzie bezużyteczne. I możesz nie uzyskać właściwego zachowania z operacji konwersji spraw.

(Przesłonięcie sortowania w zapytaniu nie ma dużego obciążenia. Jest to tylko operacja w czasie analizy).


Prawdopodobnie mniej bólu, aby mieć rozsądny domyślny ..
Erwin Brandstetter

1
Obecnie używam es_CL.utf8 w testowej bazie danych, ale dzięki twojej odpowiedzi spojrzałem trochę więcej i odkryłem, że tak utf8_unicode_cijest .
Tae

0

Używamy postgres w kontenerze dokowanym, dlatego zawsze mamy dostęp do OIOM i używamy und-x-icugo domyślnie.

Jest to wspomniane w rozdziale 23.2.2.2.2. Sortowania ICU tych Postres docs jest mowa o:

und-x-icu (dla „niezdefiniowanych”)
zestawień „root” ICU. Użyj tego, aby uzyskać rozsądny porządek sortowania niezależny od języka.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.