Estou projetando um banco de dados que armazenará dados em diferentes idiomas (usando UTF-8), então acho que a melhor maneira de exibir os resultados da consulta é ordenando-os de acordo com o idioma do usuário durante a própria consulta ( porque há mais de um maneiras corretas de fazer isso ), como segue:
SELECT a < b COLLATE "de_DE" FROM test1;
Supondo que esta seja a maneira correta de trabalhar com dados internacionais, qual é o melhor agrupamento para o próprio banco de dados? A documentação do PostgreSQL diz :
Os agrupamentos C e POSIX especificam o comportamento "C tradicional", no qual apenas as letras ASCII "A" a "Z" são tratadas como letras e a classificação é feita estritamente por valores de byte de código de caractere.
Acho que esta é a melhor escolha neste caso, ou estou errado?
(Pergunta bônus: é muito lento selecionar o agrupamento na própria consulta?).
O
C
agrupamento é a escolha certa.Tudo é um pouco mais rápido sem localidade. E como nenhum agrupamento está certo de qualquer maneira, crie o banco de dados sem agrupamento, ou seja, com
C
.Pode ser difícil ter que fornecer um agrupamento para muitas operações. No entanto, não deve haver uma diferença perceptível na velocidade entre o agrupamento padrão e um agrupamento ad-hoc. Afinal, são apenas dados não classificados e as regras de agrupamento são aplicadas durante a classificação.
Esteja ciente de que o Postgres se baseia nas configurações de localidade fornecidas pelo sistema operacional subjacente, portanto, você precisa ter localidades geradas para cada localidade a ser usada. Mais em resposta relacionada em SO aqui e aqui .
No entanto, como o @Craig já mencionou , os índices são o gargalo nesse cenário. O agrupamento do índice deve corresponder ao agrupamento do operador aplicado em muitos casos que envolvem dados de caractere.
Você pode usar o
COLLATE
especificador em índices para produzir índices correspondentes. Índices parciais podem ser a escolha perfeita se você estiver misturando dados na mesma tabela.Por exemplo, uma tabela com strings internacionais:
E você está interessado principalmente em um idioma por vez:
Em seguida, crie índices parciais como:
Um para cada idioma que você precisa.
Na verdade, a herança pode ser uma abordagem superior para uma tabela como esta. Então você pode ter um índice simples em cada tabela herdada contendo apenas strings para uma única localidade. Você precisa estar confortável com as regras especiais para tabelas herdadas, é claro.
Sugiro que você escolha um agrupamento que forneça a ordem Unicode padrão. Dessa forma, você obtém resultados sensatos, mesmo que não substitua o agrupamento em cada consulta. Infelizmente, a maioria (todos?) Os sistemas operacionais não fornecem uma localidade que é simplesmente chamada de "Unicode padrão" ou algo assim, então você terá que adivinhar e/ou pesquisar uma boa escolha. Por exemplo, no Linux/glibc, as localidades de_DE.utf8 ou en_US.utf8 simplesmente passam pelo comportamento padrão, então ambas são boas escolhas.
Não acho que usar a localidade C seja uma boa ideia, porque o comportamento padrão do seu aplicativo será inútil. E você pode não obter o comportamento adequado das operações de conversão de maiúsculas e minúsculas.
(Substituir o agrupamento em uma consulta não tem muita sobrecarga. É apenas uma operação de tempo de análise.)
Usamos o postgres em um container docker, assim sempre temos o ICU disponível e usamos
und-x-icu
como padrão.Isso é mencionado no capítulo 23.2.2.2.2. Os agrupamentos de UTI dos documentos postres mencionam: