国際データベースの照合を選択する方法は?


22

さまざまな言語(UTF-8を使用)でデータを格納するデータベースを設計しているので、クエリの結果を表示する最良の方法は、クエリ自体の実行中にユーザーの言語に従って並べることです(複数あるためそれを行う正しい方法)、次のように:

SELECT a < b COLLATE "de_DE" FROM test1;

これが国際データを処理する正しい方法であると仮定すると、データベース自体にとって最適な照合はどれですか?PostgreSQLのドキュメントによると

C照合とPOSIX照合はどちらも「従来のC」動作を指定します。この動作では、ASCII文字「A」から「Z」のみが文字として扱われ、ソートは文字コードバイト値によって厳密に行われます。

この場合、これが最良の選択だと思いますか、それとも間違っていますか?

(ボーナス質問:クエリ自体で照合順序を選択するには遅すぎますか?)。


2
苦しむ最大の問題点は、多言語DBで多くのインデックスが必要になることです。これは、照合可能なテキストのインデックスが照合に固有であるためです。ただし、特定の照合/言語内でのみ検索する傾向がある場合は、部分インデックスを使用して、インデックスサイズを制御しやすくすることができます。
クレイグリンガー

2
ソースを引用する場合、リンクを追加します。
アーウィンブランドステッター

回答:


27

C照合は、正しい選択です。

ロケールがなければ、すべてが少し速くなります。何の照合が右とにかくされていないので、データベースを作成せずに意味、照合C

多くの操作で照合を提供する必要があるのは苦痛かもしれません。ただし、デフォルトの照合とアドホック照合の速度に顕著な違いはないはずです。結局のところ、それは単にソートされていないデータであり、ソート時には照合規則が適用されます。

Postgresは基盤となるOSによって提供されるロケール設定に基づいて構築されるため、使用するロケールごとにロケールを生成する必要があることに注意してください。SOの関連する回答の詳細はこちらこちら

ただし、@ 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つ。

実際、このようなテーブルでは、継承が優れたアプローチかもしれません。次に、単一のロケールの文字列のみを含む継承された各テーブルにプレーンインデックスを設定できます。もちろん、継承されたテーブルの特別なルールに慣れる必要があります。


1
新しいデータベースにはデフォルトでCロケール(正確には「非ロケール」)を使用していますか?
ジャックダグラス14

1
@JackDouglas:いいえ、特別な場合にのみ行います。通常、その場所で一般的に使用されるロケールを使用する方がはるかに実用的です。
アーウィンブランドステッター14

13

デフォルトのUnicode順序を提供する照合を選択することをお勧めします。これにより、各クエリで照合順序をオーバーライドしなくても、正しい結果が得られます。残念ながら、ほとんどの(すべて?)オペレーティングシステムは、単に "デフォルトUnicode"またはそのような名前のロケールを提供していないため、適切な選択肢を推測または調査する必要があります。たとえば、Linux / glibcでは、de_DE.utf8またはen_US.utf8ロケールは単にデフォルトの動作を通過するだけなので、どちらも適切な選択です。

アプリケーションのデフォルトの動作は役に立たないため、Cロケールを使用することはお勧めできません。また、大文字と小文字の変換操作から適切な動作が得られない場合があります。

(クエリで照合順序をオーバーライドするのにオーバーヘッドはあまりありません。これは単なる解析時の操作です。)


おそらく、
健全

1
現在、私はテストデータベースでes_CL.utf8を使用していますが、あなたの答えのおかげで、もう少し調べて、それutf8_unicode_ciが道であることわかりました。
Tae

0

Dockerコンテナでpostgresを使用するため、常にICUが使用可能になりund-x-icu、デフォルトとして使用されます。

これについては、23.2.2.2.2章で説明しています。postres docs言及のICU照合

und-x-icu(「未定義」の場合)
ICU「ルート」照合。これを使用して、適切な言語に依存しないソート順を取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.