Почему в моем PostgreSQL ORDER BY регистр не учитывается?


27

У меня Postgres 9.4.4 работает на Debian, и я получаю следующее ORDER BYповедение:

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)

И uname -a:

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

Однако на моем iMac с Postgres 9.3.4 я получаю следующее:

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)

И то 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

Я озадачен тем, почему версия Debian не чувствительна к регистру, а версия OS X - нет. Что мне не хватает или какую другую информацию мне нужно предоставить?

Обновление : на моем Mac pg_collationтаблица показывает, что у меня есть параметры en_US.UTF-8сортировки, а в Debian - параметры en_US.utf8сортировки. Таким образом, на моем 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)

И на 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)

Так en_US.UTF-8и en_US.utf8есть разные порядки сортировки?


У меня нет Mac для тестирования, поэтому я стреляю в темноте ... Есть ли шанс, что строка 'D d a A c b CD Capacitor'не будет использоваться в качестве textполя на Mac? IE, попробуйте SELECT regexp_split_to_table('D d a A c b CD Capacitor'::text, ' ') ORDER BY 1;и посмотрите, что произойдет ...
Крис

Тот же результат. Из других новостей выясняется, что select * from pg_collationу Debian коробка есть en_US.utf8, а у OS X есть en_US.UTF-8. Использование их для явной принудительной сортировки в соответствующих полях показывает разные порядки сортировки :(
Кертис По

И я опубликовал обновление, которое могло бы объяснить проблему, но для меня это только углубляет тайну. И теперь я нашел это: stackoverflow.com/questions/19967555/… и это: stackoverflow.com/questions/27395317/…
Кертис По

7
К сожалению, Postgres использует реализацию сопоставления из ОС, что делает этот тип поведения зависимым от ОС (что я лично считаю ошибкой - СУБД должна вести себя одинаково независимо от ОС). Так что это сводится к различиям в системных библиотеках между Debian и OSX
a_horse_with_no_name

1
Между Postgres и другими частями системы будут разногласия, если порядок сортировки не будет соответствовать остальным. Я тоже предпочитаю идентичное поведение, но я бы не назвал это багом следования локали системы. В конечном счете, идентичные локали должны вести себя одинаково в разных ОС. Язык Debian кажется правильным , Apple, кажется, виновата (если нет другого объяснения).
Эрвин Брандштеттер,

Ответы:


16

Так en_US.UTF-8и en_US.utf8есть разные порядки сортировки?

Нет, они оба одинаковые, просто другое соглашение об именах.

Я озадачен тем, почему версия Debian не чувствительна к регистру, а версия OS X - нет.

Да вы правы. Это поведение по умолчанию на Mac. Параметры сортировки не работают ни в одной операционной системе BSD (включая OSX) для UTF8кодирования.

Вот ссылка, чтобы доказать это:

Проблемы с порядком сортировки (UTF8 локали не работают

Как сказал a_horse_with_no_name , Postgres использует реализацию сопоставления из ОС. Невозможно получить одинаковый результат в обеих операционных системах.

В вашем случае вы можете (я , возможно , сказал) сделать так: ORDER BY lower(fieldname).


2
Будьте внимательны, чтобы проверить производительность при использовании ORDER BY function()потенциально больших наборов результатов - поскольку это останавливает использование индекса для сортировки, это почти наверняка вызовет дополнительную операцию сортировки (возможно, на диске), и это может изменить метод планировщика запросов для более широкой атаки на ваш запрос. ,
Дэвид Спиллетт

@ Дэвид Спиллетт: Вы правы насчет функции заказа. Я думаю, что мой ответ более сфокусирован на том, почему у OP разные способы сортировки в iMac и Debian. Спасибо
JSapkota

1
Да, ваш ответ в порядке и полностью охватывает вопрос. Упоминание о «тестировании с реальными данными после изменений, которые могут повлиять на план запроса» стало для меня привычной реакцией (очень похоже на упоминание о тестировании в любом обсуждении резервных копий и т. Д.), Поскольку об этом легко забыть (и люди часто это делают) или даже не знаю, в случае людей, более новых для работы с базой данных.
Дэвид Спиллетт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.