LC_CTYPE'nin PostgreSQL veritabanı üzerindeki etkisi nedir?


25

Böylece, üzerinde PostgreSQL bulunan birkaç Debian sunucusu var. Tarihsel olarak, bu sunucular ve PostgreSQL Latin 9 karakter kümesi ile yerelleştirildi ve o zamanlar iyiydi. Şimdi Polonyaca, Yunanca veya Çince gibi şeylerle başa çıkmak zorundayız, bu yüzden bunu değiştirmek gittikçe büyüyen bir konu haline geldi.

UTF8 veritabanı oluşturmaya çalıştığımda şu mesajı aldım:

HATA: UTF8 kodlaması yerel ayar fr_FR ile eşleşmiyor Detay: Seçilen LC_CTYPE ayarı LATIN9 kodlamasını gerektirir.

Birkaç kez eski dostum Google ile konuyla ilgili bazı araştırmalar yaptım ve bulabildiğim tek şey Debian'ı güncellemek, LANGPostgreSQL'i doğru karakter grubuyla yeniden düzenlemek, tüm LC_sistem değişkenlerini ve diğer karanlık çözümleri düzeltmek gibi aşırı karmaşık prosedürlerdi . Şimdilik bu konuyu bir kenara bıraktık.

Son zamanlarda, yine geri geldi, Yunanlılar eşyayı istiyor ve Latin 9 da istemiyor. Ve yine bu konuyu araştırırken, bir meslektaşım yanıma geldi ve “Hayır, kolay, bak” dedi.

Hiçbir şey düzenlemedi, sihir numaraları yapmadı, sadece şu SQL sorgusunu yaptı:

CREATE DATABASE my_utf8_db
  WITH ENCODING='UTF8'
       OWNER=admin
       TEMPLATE=template0
       LC_COLLATE='C'
       LC_CTYPE='C'
       CONNECTION LIMIT=-1
       TABLESPACE=pg_default;

Ve iyi çalıştı.

Aslında bilmiyordum LC_CTYPE='C've bunu kullanmanın Google’daki ilk çözümlerde ve hatta Stack Overflow’ta olmadığına şaşırdım. Etrafıma baktım ve yalnızca PostgreSQL belgelerinde bahsettim.

LC_CTYPE C veya POSIX ise, herhangi bir karakter setine izin verilir, ancak LC_CTYPE'nin diğer ayarları için düzgün çalışacak yalnızca bir karakter seti vardır. LC_CTYPE ayarı initdb tarafından dondurulduğundan, bir kümenin farklı veritabanlarında farklı kodlamaları kullanmak için görünen esneklik, C veya POSIX yerel ayarını seçtiğinizde (dolayısıyla gerçek yerel ayar farkındalığını devre dışı bırakarak) dışında gerçekten daha teoriktir.

Bu yüzden beni meraklandırdı, bu çok kolay, çok mükemmel, olumsuz nedir? Ve henüz bir cevap bulmakta zorlanıyorum. Yani burada buraya gönderme geliyorum:

tl; dr: Belirli bir yerelleştirmeyi kullanmanın olumsuz tarafı nedir LC_CTYPE='C'? Bunu yapmak kötü mü? Ne kırmayı beklemeliyim?

Yanıtlar:


25

Belirli bir yerelleştirme üzerinde LC_CTYPE = 'C' kullanmanın olumsuz tarafı nedir

Belgeler, Yerel Ayar Desteği'nde yereller ve SQL özellikleri arasındaki ilişkiden bahseder :

Yerel ayar aşağıdaki SQL özelliklerini etkiler:

  • ORDER BY veya standart karşılaştırma işleçlerini metin verileri üzerinde kullanarak sorgularda sıralama düzeni

  • Üst, alt ve initcap işlevleri

  • Desen eşleştirme operatörleri (LIKE, SIMILAR TO ve POSIX tarzı normal ifadeler); locales, hem büyük / küçük harfe duyarlı olmayan eşlemeyi hem de karakterlerin karakter sınıfı normal ifadelerle sınıflandırılmasını etkiler

  • To_char işlev ailesi

  • LIKE cümlecikleriyle endeks kullanabilme

İlk madde (sıralama düzeni) yaklaşık LC_COLLATE, diğerleri ise yaklaşık olarak görünüyor LC_CTYPE.

LC_COLLATE

LC_COLLATEDizeler arasındaki karşılaştırmaları etkiler. Uygulamada, en görünür etki sıralama düzenidir. LC_COLLATE='C'(veya POSIXbunun eş anlamlısıdır), karşılaştırma yapan bayt sırasını ifade ederken, language_REGIONformdaki bir yerel ayar kültürel kuralların karşılaştırmaları yönlendireceği anlamına gelir.

UTF-8 veri tabanından çalıştırılan fransız isimleri içeren bir örnek:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
 AS l(firstname)
order by firstname collate "fr_FR";

Sonuç:

 İsim 
-----------
 béatrice
 Bérénice
 bernard
 boris

béatriceönceden gelir boris, çünkü aksanlı E, aksanlı sanki O ile karşılaştırır. Bu kültürel bir kuraldır.

Bu, Cyerel ayarlarda olanlardan farklıdır :

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris')) 
 AS l(firstname)
order by firstname collate "C";

Sonuç:

 İsim 
-----------
 bernard
 boris
 béatrice
 Bérénice

Şimdi vurgulu E'li isimler listenin sonuna itilir. éUTF-8'de byte gösterimi onaltılıktır C3 A9ve obunun içindir 6f. yerelin altında c3olduğundan daha büyük .6fC'béatrice' > 'boris'

Bu sadece aksan değil. Tireleme, noktalama işaretleri ve tuhaf karakterler içeren daha karmaşık kurallar vardır œ. Her bölgede tuhaf kültürel kurallar beklenmektedir.

Şimdi, karşılaştırılacak dizeler farklı dilleri birbirine karıştırıyorsa firstname, dünyanın dört bir yanından insanlar için bir sütun varken , farklı diller için farklı alfabeler tasarlanmadığı için herhangi bir yerel ayarın baskın olmaması gerektiği olabilir. birbirlerine karşı sıralanır.

Bu durumda Crasyonel bir seçimdir ve daha hızlı olma avantajına sahiptir, çünkü hiçbir şey saf bayt karşılaştırmalarını geçemez.

LC_CTYPE

Having LC_CTYPE'C' olarak set ima gibi o C fonksiyonları isupper(c)veya tolower(c)yalnızca US-ASCII aralığındaki karakterlerden beklenen sonuçları verir (yukarı Unicode kod noktası 0x7F olduğunu).

SQL fonksiyonları beğendiğinizden upper(), lower()ya initcap bu libc fonksiyonların üstünde Postgres uygulanır, bunlar en kısa sürede dizelerinde US-ASCII karakterleri olduğu gibi bundan etkilenecek ediyoruz.

Örnek:

test=> show lc_ctype;
  lc_ctype   
-------------
 fr_FR.UTF-8
(1 row)

-- Good result
test=> select initcap('élysée');
 initcap 
---------
 Élysée
(1 row)

-- Wrong result
-- collate "C" is the same as if the db has been created with lc_ctype='C'
test=> select initcap('élysée' collate "C");
 initcap 
---------
 éLyséE
(1 row)

İçin Cyerel ayarı, ébir sınıflandırılamaz karakter olarak ele alınır.

Benzer şekilde, yanlış ifadeler düzenli ifadelerle de elde edilir:

test=> select 'élysée' ~ '^\w+$';
 ?column? 
----------
 t
(1 row)

test=> select 'élysée' COLLATE "C" ~ '^\w+$';
 ?column? 
----------
 f
(1 row)

Yani doğru anlamış olsam, UTF-8 sunucusunu yapsanız bile sipariş sorununu çözebilir miyiz? Sistem LC_CTYPE’nin UTF-8’de ayarlanmış olması veya PostgreSQL’in UTF-8’de derlenmesi, sizin belirttiğiniz karşılaştırma problemiyle sonuçlanacaktır.
Gregoire D.

Bunu genişletmek için karşılaştırmaları yerel olarak doğru olacak şekilde harmanlamayı sorgulamaya zorlamak mümkün olur mu?
Gregoire D.

Evet, bireysel dize karşılaştırmaları collate "C"sonrasındaki cevapta yaptığım gibi kendi harmanlama kurallarını yerleştirebilir order by. Uygulamanızın ihtiyaç duyup duymadığı ve nerede olduğunu belirlemek sizin sorumluluğunuzdadır. Dışarıdaki çoğu uygulama gerçekten umursamıyor.
Daniel Vérité

1
Ayrıca, tek tek sütunların COLLATEveritabanından farklı olan bir belirteci olabileceğini unutmayın .
Daniel Vérité

2
Bu cevap gerçekten LC_COLLATE içindir, LC_CTYPE değil. LC_CTYPE, bir karakterin rakam, harf, boşluk, noktalama vb.
Olup

10

Daniel'in harmanlama kullanarak sıralama hakkındaki kabul edilen cevabına atıfta bulunarak, Mac’te PostgreSQL kullanıyorsanız, işletim sistemi seviyesindeki bazı harmanlamalar için yetersiz ayarlar nedeniyle beklediğiniz harmanlamanın beklemeyeceğinizi unutmayın. Bu konuda daha fazla bilgiyi buradan okuyabilirsiniz:

http://www.postgresql.org/message-id/4B4E845F.80906@postnewspapers.com.au

Bu özellikle PostgreSQL'e özgü bir sorun değil, Mac'in harmanlama ayarları için varsayılan yapılandırmasıyla ilgili bir sorun. Mevcut sistemim OS X El Capitan Sürüm 10.11'de PostgreSQL 9.3 kullanıyor ve bu sorundan muzdarip. Sistemim, “fr_FR” veya “en_US” harmanlamasını kullanmamdan bağımsız olarak aynı sorgu sonuçlarını döndürüyor. Örneğin:

“Fr_FR” harmanlamasını kullanarak:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "fr_FR";

results:
==============
bernard
boris
béatrice
bérénice

“En_US” harmanlama kullanarak:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "en_US";

results:
==============
bernard
boris
béatrice
bérénice

Sistemimde, harmanlama ayarları (işletim sistemi düzeyinde), diff çalıştırılarak kabukta gösterildiği gibi “fr_FR” ve “en_US” için aynıdır:

cd /usr/share/locale
diff fr_FR.UTF-8/LC_COLLATE en_US.UTF-8/LC_COLLATE

Umarım bu ek bilgi, PostgreSQL kullanan ve bu sorundan muzdarip olan bir Mac'te okuyan herkes için faydalıdır.


Modern Mac'lerde çalışmasını nasıl sağlayabilirim. Mac'inizde çalışması için herhangi bir şeyden geçtiniz mi?
Kumar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.