web-dev-qa-db-fra.com

Comment choisir un classement pour une base de données internationale?

Je conçois une base de données qui stockera des données dans différentes langues (en utilisant UTF-8), donc je pense que la meilleure façon d'afficher les résultats de la requête est de les ordonner en fonction de la langue de l'utilisateur pendant la requête elle-même ( car il existe plusieurs façons correctes de le faire ), comme suit:

SELECT a < b COLLATE "de_DE" FROM test1;

En supposant que c'est la bonne façon de travailler avec des données internationales, quel est le meilleur classement pour la base de données elle-même? La documentation PostgreSQL dit :

Les classements C et POSIX spécifient tous deux un comportement "C traditionnel", dans lequel seules les lettres ASCII "A" à "Z" sont traitées comme des lettres, et le tri est strictement effectué par des valeurs d'octet de code de caractère .

Je pense que c'est le meilleur choix dans ce cas, ou je me trompe?

(Question bonus: est-il trop lent pour sélectionner le classement dans la requête elle-même?).

22
Tae

Le classement C est le bon choix.

Tout est un peu plus rapide sans locale. Et comme aucun classement n'est correct de toute façon, créez la base de données sans classement, c'est-à-dire avec C.

Il peut être difficile de devoir fournir un classement pour de nombreuses opérations. Cependant, il ne devrait pas y avoir de différence notable de vitesse entre le classement par défaut et un classement ad hoc. Après tout, ce ne sont que des données non triées et des règles de classement sont appliquées lors du tri.

Sachez que Postgres s'appuie sur les paramètres régionaux fournis par le système d'exploitation sous-jacent, vous devez donc générer des paramètres régionaux pour chaque paramètre régional à utiliser. Plus dans la réponse associée sur SO ici et ici .

Cependant, comme @ Craig déjà mentionné , les index sont le goulot d'étranglement dans ce scénario. Le classement de l'index doit correspondre au classement de l'opérateur appliqué dans de nombreux cas impliquant des données de caractères.

Vous pouvez utiliser le spécificateur COLLATE dans les index pour produire des index correspondants. Index partiels peut être le choix parfait si vous mélangez des données dans la même table.

Par exemple, une table avec des chaînes internationales:

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

Et vous êtes surtout intéressé par une langue à la fois:

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

Créez ensuite des index partiels comme:

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

Un pour chaque langue dont vous avez besoin.

En fait, l'héritage pourrait être une approche supérieure pour une table comme celle-ci. Ensuite, vous pouvez avoir un index simple sur chaque table héritée contenant uniquement des chaînes pour un seul paramètre régional. Vous devez bien sûr être à l'aise avec les règles spéciales pour les tables héritées.

27
Erwin Brandstetter

Je vous suggère de choisir un classement qui fournit la commande Unicode par défaut. De cette façon, vous obtenez des résultats sensés même si vous ne remplacez pas le classement dans chaque requête. Malheureusement, la plupart (tous?) Des systèmes d'exploitation ne fournissent pas de paramètres régionaux qui sont simplement nommés "Unicode par défaut" ou quelque chose comme ça, vous devrez donc deviner et/ou rechercher un bon choix. Par exemple, sur Linux/glibc, les paramètres régionaux de_DE.utf8 ou en_US.utf8 passent simplement par le comportement par défaut, donc les deux sont de bons choix.

Je ne pense pas que l'utilisation des paramètres régionaux C soit une bonne idée, car le comportement par défaut de votre application sera alors inutile. Et vous pourriez ne pas obtenir un comportement correct des opérations de conversion de cas.

(Remplacer le classement dans une requête n'a pas beaucoup de surcharge. C'est juste une opération d'analyse.)

13
Peter Eisentraut

Nous utilisons des postgres dans un conteneur docker, donc nous avons toujours ICU disponible et utilisons und-x-icu par défaut.

Ceci est mentionné dans le chapitre 23.2.2.2.2. ICU collations des documents postres mentionne:

und-x-icu (pour "non défini")
Collation ICU "racine". Utilisez-le pour obtenir un ordre de tri indépendant de la langue.

0
TmTron