Mengapa ORDER PostgreSQL saya BY-case-sensitive?

27

Saya memiliki Postgres 9.4.4 yang berjalan di Debian dan saya mendapatkan ORDER BYperilaku berikut :

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)

Dan uname -a:

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

Namun, di iMac saya, dengan Postgres 9.3.4, saya mendapatkan yang berikut:

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)

Dan 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

Saya bingung oleh mengapa versi Debian tampaknya tidak sensitif huruf besar dan versi OS X tidak. Apa yang saya lewatkan, atau informasi lain apa yang perlu saya berikan?

Pembaruan : Di Mac saya, pg_collationtabel menunjukkan saya memiliki en_US.UTF-8susunan, tetapi di Debian, saya memiliki en_US.utf8susunan. Jadi, di Mac saya:

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)

Dan di 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)

Jadi en_US.UTF-8dan en_US.utf8punya berbagai macam pesanan?

Curtis Poe
sumber
Saya tidak punya Mac untuk diuji, jadi saya menembak dalam kegelapan di sini ... Apakah ada kemungkinan bahwa string 'D d a A c b CD Capacitor'tidak dilemparkan sebagai textbidang pada Mac? Yaitu, coba SELECT regexp_split_to_table('D d a A c b CD Capacitor'::text, ' ') ORDER BY 1;dan lihat apa yang terjadi ...
Chris
Hasil yang sama Dalam berita lain, ternyata select * from pg_collationkotak Debian menunjukkan memiliki en_US.utf8, sedangkan OS X miliki en_US.UTF-8. Menggunakan mereka untuk secara eksplisit memaksa collation pada kotak masing-masing menunjukkan urutan berbeda :(
Curtis Poe
Dan saya telah memposting pembaruan yang mungkin menjelaskan masalahnya, tetapi bagi saya, itu hanya memperdalam misteri. Dan saya sekarang telah menemukan ini: stackoverflow.com/questions/19967555/… dan ini: stackoverflow.com/questions/27395317/…
Curtis Poe
7
Sayangnya Postgres menggunakan implementasi collation dari OS yang membuat perilaku seperti ini bergantung pada OS (yang secara pribadi saya anggap sebagai bug - sebuah DBMS harus berperilaku identik terlepas dari OS). Jadi ini bermuara pada perbedaan dalam sistem perpustakaan antara Debian dan OSX
a_horse_with_no_name
1
Akan ada perbedaan pendapat antara Postgres dan bagian lain dari sistem jika urutan sortir tidak sesuai dengan yang lain. Saya juga lebih suka perilaku yang identik, tetapi saya tidak akan menyebutnya bug untuk mengikuti lokal sistem. Pada akhirnya, lokal yang identik harus berperilaku identik di seluruh OS. The Debian lokal tampaknya benar , Apple tampaknya bersalah (kecuali ada beberapa penjelasan lain).
Erwin Brandstetter

Jawaban:

16

Jadi en_US.UTF-8dan en_US.utf8punya berbagai macam pesanan?

Tidak, keduanya sama, hanya konvensi penamaan yang berbeda.

Saya bingung oleh mengapa versi Debian tampaknya tidak sensitif huruf besar dan versi OS X tidak.

Ya kamu benar. Ini adalah perilaku default di Mac. Collations tidak berfungsi pada OS BSD-ish (termasuk OSX) untuk UTF8encoding.

Berikut ini adalah referensi untuk membuktikan bahwa:

Masalah dengan urutan pengurutan (lokal UTF8 tidak berfungsi

Seperti yang dikatakan a_horse_with_no_name , Postgres menggunakan implementasi collation dari OS. Tidak ada cara untuk mendapatkan hasil yang sama di kedua sistem operasi.

Dalam kasus Anda Anda mungkin (saya katakan mungkin) lakukan seperti ini: ORDER BY lower(fieldname).

JSapkota
sumber
2
Berhati-hatilah untuk memverifikasi kinerja saat menggunakan ORDER BY function()pada hasil yang berpotensi besar - karena menghentikan indeks yang digunakan untuk pengurutan, itu hampir pasti akan menyebabkan operasi pengurutan ekstra (mungkin pada disk) dan dapat mengubah metode perencana kueri untuk menyerang kueri Anda secara lebih luas .
David Spillett
@ David Spillett: Anda benar tentang fungsi Order. Saya pikir jawaban saya lebih fokus pada mengapa OP memiliki mode penyortiran berbeda di iMac dan Debian. Terima kasih
JSapkota
1
Ya, jawaban Anda baik-baik saja dan mencakup pertanyaan sepenuhnya. Menyebutkan "pengujian dengan data nyata setelah perubahan yang mungkin memengaruhi rencana kueri" telah menjadi reaksi kebiasaan dalam diri saya (seperti menyebut pengujian dalam setiap diskusi tentang cadangan, dan sebagainya) karena mudah dilupakan (dan orang sering melakukannya) atau bahkan tidak tahu dalam kasus orang yang lebih baru untuk pekerjaan basis data.
David Spillett