Pourquoi mon PostgreSQL ORDER BY est-il insensible à la casse?

27

J'ai Postgres 9.4.4 en cours d'exécution sur Debian et j'obtiens le ORDER BYcomportement suivant :

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)

Et uname -a:

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

Cependant, sur mon iMac, avec Postgres 9.3.4, j'obtiens ce qui suit:

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)

Et le 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

Je ne comprends pas pourquoi la version Debian semble être insensible à la casse et la version OS X ne l'est pas. Que me manque-t-il ou quelles autres informations dois-je fournir?

Mise à jour : Sur mon Mac, le pg_collationtableau montre que j'ai un en_US.UTF-8classement, mais sur Debian, j'ai un en_US.utf8classement. Ainsi, sur mon 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)

Et sur 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)

Alors en_US.UTF-8et en_US.utf8avez-vous des ordres de tri différents?

Curtis Poe
la source
Je n'ai pas de Mac pour tester, donc je tire dans le noir ici ... Y a-t-il une chance que la chaîne 'D d a A c b CD Capacitor'ne soit pas convertie en textchamp sur le Mac? IE, essayez de SELECT regexp_split_to_table('D d a A c b CD Capacitor'::text, ' ') ORDER BY 1;voir ce qui se passe ...
Chris
Même résultat. Dans d'autres nouvelles, il s'avère que select * from pg_collationla boîte Debian a en_US.utf8, tandis que OS X a en_US.UTF-8. L'utilisation de ceux-ci pour forcer explicitement le classement sur les boîtes respectives montre différents ordres de tri :(
Curtis Poe
Et j'ai publié une mise à jour qui pourrait expliquer le problème, mais pour moi, cela ne fait qu'approfondir le mystère. Et j'ai maintenant trouvé ceci: stackoverflow.com/questions/19967555/… et ceci: stackoverflow.com/questions/27395317/…
Curtis Poe
7
Malheureusement, Postgres utilise l'implémentation de classement du système d'exploitation qui rend ce type de comportement dépendant du système d'exploitation (que je considère personnellement comme un bogue - un SGBD devrait se comporter de manière identique quel que soit le système d'exploitation). Cela se résume donc aux différences dans les bibliothèques système entre Debian et OSX
a_horse_with_no_name
1
Il y aura un désaccord entre Postgres et d'autres parties du système si l'ordre de tri ne correspond pas au reste. Moi aussi, je préfère un comportement identique, mais je n'appellerais pas cela un bug pour suivre les paramètres régionaux du système. En fin de compte, les paramètres régionaux identiques devraient se comporter de manière identique sur l'ensemble du système d'exploitation. Les paramètres régionaux Debian semblent corrects , Apple semble être en faute (à moins qu'il n'y ait une autre explication).
Erwin Brandstetter

Réponses:

16

Alors en_US.UTF-8et en_US.utf8avez-vous des ordres de tri différents?

Non, ces deux sont identiques, juste une convention de dénomination différente.

Je ne comprends pas pourquoi la version Debian semble être insensible à la casse et la version OS X ne l'est pas.

Oui vous avez raison. Il s'agit du comportement par défaut sur Mac. Les classements ne fonctionnent sur aucun système d'exploitation BSD (y compris OSX) pour l' UTF8encodage.

Voici une référence pour prouver que:

Problèmes avec l'ordre de tri (les locales UTF8 ne fonctionnent pas

Comme l'a dit a_horse_with_no_name , Postgres utilise l'implémentation de classement à partir du système d'exploitation. Il n'y a aucun moyen d'obtenir le même résultat sur les deux systèmes d'exploitation.

Dans votre cas , vous pouvez (je l' ai dit peut - être) faire comme ceci: ORDER BY lower(fieldname).

JSapkota
la source
2
Prenez soin de vérifier les performances lors de l'utilisation ORDER BY function()sur des ensembles de résultats potentiellement volumineux - car cela empêche un index d'être utilisé pour le tri, il provoquera presque certainement une opération de tri supplémentaire (peut-être sur le disque) et cela peut changer la méthode du planificateur de requêtes pour attaquer votre requête plus largement .
David Spillett
@David Spillett: Vous avez raison sur la fonction Ordre. Je pense que ma réponse est plus centrée sur les raisons pour lesquelles l'OP a un mode de tri différent dans iMac et Debian. Merci
JSapkota
1
Oui, votre réponse est parfaitement correcte et couvre complètement la question. Mentionner "tester avec des données réelles après des changements qui pourraient affecter le plan de requête" est devenu une réaction habituelle en moi (tout comme mentionner les tests dans toute discussion sur les sauvegardes, etc.) car il est facile d'oublier (et les gens le font souvent) ou ne sait même pas dans le cas des personnes plus récentes pour le travail de base de données.
David Spillett