Por que meu PostgreSQL ORDER BY não diferencia maiúsculas de minúsculas?

27

Tenho o Postgres 9.4.4 em execução no Debian e recebo o seguinte ORDER BYcomportamento:

veure_test=# show LC_COLLATE;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)

veure_test=# SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') ORDER BY 1;
 regexp_split_to_table 
-----------------------
 a
 A
 b
 c
 Capacitor
 CD
 d
 D
(8 rows)

E uname -a:

Linux ---- 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1 x86_64 GNU/Linux

No entanto, no meu iMac, com o Postgres 9.3.4, recebo o seguinte:

veure_test=# show LC_COLLATE;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)

veure_test=# SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') ORDER BY 1;
 regexp_split_to_table 
-----------------------
 A
 CD
 Capacitor
 D
 a
 b
 c
 d
(8 rows)

E o uname -a:

Darwin ---- 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64

Estou perplexo com o motivo pelo qual a versão Debian parece não fazer distinção entre maiúsculas e minúsculas e a versão do OS X não. O que estou faltando ou que outras informações eu preciso fornecer?

Atualização : No meu Mac, a pg_collationtabela mostra que tenho um en_US.UTF-8agrupamento, mas no Debian, tenho um en_US.utf8agrupamento. Assim, no meu Mac:

veure_test=# with foo as (
SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') as bar
   )
SELECT bar FROM foo
ORDER BY bar collate "en_US.UTF-8";                                                                                                                                                                                      
    bar    
-----------
 A
 CD
 Capacitor
 D
 a
 b
 c
 d
(8 rows)

E no Debian:

veure_test=# with foo as (
SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') as bar
   )
SELECT bar FROM foo
ORDER BY bar collate "en_US.utf8";
    bar    
-----------
 a
 A
 b
 c
 Capacitor
 CD
 d
 D
(8 rows)

Então, en_US.UTF-8e en_US.utf8tem ordens de classificação diferentes?

Curtis Poe
fonte
Não tenho um Mac para testar, por isso estou filmando no escuro aqui ... Alguma chance de a corda 'D d a A c b CD Capacitor'não estar sendo lançada como um textcampo no Mac? IE, tente SELECT regexp_split_to_table('D d a A c b CD Capacitor'::text, ' ') ORDER BY 1;ver o que acontece ...
Chris
Mesmo resultado. Em outras notícias, acontece que select * from pg_collationmostra a caixa Debian en_US.utf8, enquanto o OS X possui en_US.UTF-8. Usando os forçar explicitamente agrupamento nas caixas respectivas mostra diferentes ordens de classificação :(
Curtis Poe
E eu publiquei uma atualização que pode explicar o problema, mas para mim, isso apenas aprofunda o mistério. E eu tenho encontrado agora isto: stackoverflow.com/questions/19967555/... e isso: stackoverflow.com/questions/27395317/...
Curtis Poe
7
Infelizmente, o Postgres usa a implementação de agrupamento do sistema operacional, o que torna esse tipo de comportamento dependente do sistema operacional (que eu pessoalmente considero um bug - um DBMS deve se comportar de forma idêntica, independentemente do sistema operacional). Portanto, esta se resume a diferença nas bibliotecas sistema entre Debian e OSX
a_horse_with_no_name
11
Haverá desacordo entre o Postgres e outras partes do sistema se a ordem de classificação não estiver alinhada com o restante. Eu também prefiro comportamento idêntico, mas não chamaria de bug seguir a localidade do sistema. Por fim, locais idênticos devem se comportar de forma idêntica no sistema operacional. O local do Debian parece correto , a Apple parece estar com falha (a menos que haja outra explicação).
Erwin Brandstetter

Respostas:

16

Então, en_US.UTF-8e en_US.utf8tem ordens de classificação diferentes?

Não, ambos são iguais, apenas uma convenção de nomenclatura diferente.

Estou perplexo com o motivo pelo qual a versão Debian parece não fazer distinção entre maiúsculas e minúsculas e a versão do OS X não.

Sim você está correto. Esse é o comportamento padrão no Mac. Os agrupamentos não funcionam em nenhum sistema operacional BSD (incluindo OSX) para UTF8codificação.

Aqui está uma referência para provar que:

Problemas com a ordem de classificação (os códigos de idioma UTF8 não funcionam

Como um a_horse_with_no_name disse, o Postgres usa a implementação de agrupamento do sistema operacional. Não há como obter o mesmo resultado nos dois sistemas operacionais.

No seu caso, você pode (eu disse talvez) fazer assim: ORDER BY lower(fieldname).

JSapkota
fonte
2
Tome cuidado para verificar o desempenho ao usar ORDER BY function()em conjuntos de resultados potencialmente grandes - porque ele interrompe a utilização de um índice para a classificação, quase certamente causará uma operação de classificação extra (possivelmente em disco) e pode alterar o método do planejador de consulta de atacar sua consulta mais amplamente .
David Spillett
@ David Spillett: Você está certo sobre a função Order. Eu acho que minha resposta está mais focada em por que o OP está tendo uma maneira diferente de classificação no iMac e no Debian. Graças
JSapkota
11
Sim, sua resposta está perfeitamente correta e cobre a questão completamente. Mencionar "testar com dados reais após alterações que possam afetar o plano de consulta" se tornou uma reação habitual para mim (assim como mencionar o teste em qualquer discussão sobre backups e assim por diante), pois é fácil esquecer (e as pessoas costumam fazer) ou nem sei no caso de pessoas mais novas no trabalho de banco de dados.
David Spillett