¿Cómo elegir una clasificación para una base de datos internacional?

22

Estoy diseñando una base de datos que almacenará datos en diferentes idiomas (usando UTF-8), por lo que creo que la mejor manera de mostrar los resultados de la consulta es ordenarla de acuerdo con el idioma del usuario durante la consulta en sí ( porque hay más de uno formas correctas de hacerlo ), de la siguiente manera:

SELECT a < b COLLATE "de_DE" FROM test1;

Suponiendo que esta sea la forma correcta de trabajar con datos internacionales, ¿cuál es la mejor recopilación para la base de datos en sí? La documentación de PostgreSQL dice :

Las intercalaciones C y POSIX especifican el comportamiento "C tradicional", en el que solo las letras ASCII "A" a "Z" se tratan como letras, y la clasificación se realiza estrictamente por valores de bytes de código de caracteres.

Creo que esta es la mejor opción en este caso, ¿o me equivoco?

(Pregunta adicional: ¿es demasiado lento para seleccionar la clasificación en la consulta en sí?).

Tae
fuente
2
El mayor problema que sufrirá es que en una base de datos en varios idiomas necesita muchos índices, ya que los índices en texto contraíble son específicos de la clasificación. Sin embargo, si tiende a buscar solo dentro de una colación / lenguaje particular, puede usar índices parciales para ayudar a mantener el tamaño del índice bajo control.
Craig Ringer
2
Al citar una fuente, agregue un enlace.
Erwin Brandstetter

Respuestas:

27

La Ccolación es la elección correcta.

Todo es un poco más rápido sin configuración regional. Y como de todos modos no hay una clasificación correcta, cree la base de datos sin clasificación, es decir, con C.

Puede ser una molestia tener que proporcionar una recopilación para muchas operaciones. Sin embargo, no debería haber una diferencia notable en la velocidad entre la clasificación predeterminada y una clasificación ad-hoc. Después de todo, solo son datos sin clasificar, y las reglas de clasificación se aplican al ordenar.

Tenga en cuenta que Postgres se basa en la configuración regional proporcionada por el sistema operativo subyacente, por lo que debe tener locales generados para cada configuración regional que se utilizará. Más en la respuesta relacionada sobre SO aquí y aquí .

Sin embargo, como @Craig ya mencionó , los índices son el cuello de botella en este escenario. La clasificación del índice tiene que coincidir con la clasificación del operador aplicado en muchos casos que involucran datos de caracteres.

Puede usar el COLLATEespecificador en los índices para producir índices coincidentes. Los índices parciales pueden ser la elección perfecta si está mezclando datos en la misma tabla.

Por ejemplo, una tabla con cadenas internacionales:

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

Y usted está principalmente interesado en un idioma a la vez:

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

Luego cree índices parciales como:

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

Uno para cada idioma que necesites.

En realidad, la herencia podría ser un enfoque superior para una tabla como esta. Entonces puede tener un índice simple en cada tabla heredada que contenga solo cadenas para una sola configuración regional. Por supuesto, debe sentirse cómodo con las reglas especiales para las tablas heredadas.

Erwin Brandstetter
fuente
1
¿Utiliza la configuración regional C (o "no configuración regional" para ser precisos) de forma predeterminada para cualquier nueva base de datos?
Jack Douglas
1
@JackDouglas: No, solo haría eso para casos especiales. Por lo general, es mucho más práctico trabajar con la configuración regional generalmente utilizada en el lugar.
Erwin Brandstetter
13

Le sugiero que elija una clasificación que proporcione el orden predeterminado de Unicode. De esa manera, obtendrá resultados razonables incluso si no anula la clasificación en cada consulta. Desafortunadamente, la mayoría de los sistemas operativos (¿todos?) No proporcionan una configuración regional que simplemente se denomina "Unicode predeterminado" o algo así, por lo que tendrá que adivinar y / o investigar una buena opción. Por ejemplo, en Linux / glibc, las configuraciones regionales de_DE.utf8 o en_US.utf8 simplemente pasan por el comportamiento predeterminado, por lo que ambas son buenas opciones.

No creo que usar la configuración regional C sea una buena idea, porque el comportamiento predeterminado de su aplicación será inútil. Y es posible que no obtenga un comportamiento adecuado de las operaciones de conversión de casos.

(Anular la intercalación en una consulta no tiene mucha sobrecarga. Es solo una operación de tiempo de análisis).

Peter Eisentraut
fuente
Probablemente menos dolor por tener un defecto sano ...
Erwin Brandstetter
1
Actualmente estoy usando es_CL.utf8 en una base de datos de prueba, pero gracias a su respuesta busqué un poco más y descubrí que ese utf8_unicode_cies el camino a seguir .
Tae
0

Usamos postgres en un contenedor acoplable, por lo que siempre tenemos ICU disponible y usamos und-x-icupor defecto.

Esto se menciona en el capítulo 23.2.2.2.2. Las colaciones de la UCI de los documentos postres mencionan:

und-x-icu (para "indefinido")
UCI colación "raíz". Use esto para obtener un orden razonable de agnóstico del lenguaje.

TmTron
fuente