Saya merancang basis data yang akan menyimpan data dalam berbagai bahasa (menggunakan UTF-8), jadi saya pikir cara terbaik untuk menampilkan hasil kueri adalah memesannya sesuai dengan bahasa pengguna selama kueri itu sendiri ( karena ada lebih dari satu cara yang benar untuk melakukannya ), sebagai berikut:
SELECT a < b COLLATE "de_DE" FROM test1;
Dengan asumsi ini adalah cara yang benar untuk bekerja dengan data internasional, yang merupakan pemeriksaan terbaik untuk database itu sendiri? Dokumentasi PostgreSQL mengatakan :
Kolaborasi C dan POSIX keduanya menentukan perilaku "C tradisional", di mana hanya huruf ASCII "A" hingga "Z" yang diperlakukan sebagai huruf, dan pengurutan dilakukan secara ketat oleh nilai byte kode karakter.
Saya pikir ini adalah pilihan terbaik dalam kasus ini, atau apakah saya salah?
(Pertanyaan bonus: apakah terlalu lambat untuk memilih susunan dalam permintaan itu sendiri?).
Jawaban:
The
C
pemeriksaan adalah pilihan yang tepat.Semuanya sedikit lebih cepat tanpa lokal. Dan karena tidak ada susunan yang benar, buat basis data tanpa susunan , artinya dengan
C
.Mungkin menyusahkan harus menyediakan pemeriksaan untuk banyak operasi. Seharusnya tidak ada perbedaan yang mencolok dalam kecepatan antara susunan standar dan susunan ad-hoc. Lagi pula itu hanya data yang tidak disortir, dan aturan pemeriksaan diterapkan saat menyortir.
Ketahuilah bahwa Postgres dibuat berdasarkan pengaturan lokal yang disediakan oleh OS yang mendasarinya, jadi Anda perlu membuat lokal yang dihasilkan untuk setiap lokal yang akan digunakan. Lebih banyak jawaban terkait pada SO di sini dan di sini .
Namun, seperti @Craig sudah sebutkan , indeks adalah hambatan dalam skenario ini. Susunan indeks harus cocok dengan susunan operator yang diterapkan dalam banyak kasus yang melibatkan data karakter.
Anda dapat menggunakan
COLLATE
specifier dalam indeks untuk menghasilkan indeks yang cocok. Indeks parsial mungkin merupakan pilihan yang sempurna jika Anda mencampur data dalam tabel yang sama.Misalnya, tabel dengan string internasional:
Dan Anda sebagian besar tertarik pada satu bahasa pada satu waktu:
Kemudian buat indeks parsial seperti:
Satu untuk setiap bahasa yang Anda butuhkan.
Sebenarnya, pewarisan mungkin merupakan pendekatan yang unggul untuk tabel seperti ini. Kemudian Anda dapat memiliki indeks biasa pada setiap tabel yang diwarisi yang hanya berisi string untuk satu lokal. Anda harus merasa nyaman dengan aturan khusus untuk tabel yang diwarisi, tentu saja.
sumber
Saya sarankan Anda memilih collation yang menyediakan pemesanan Unicode default. Dengan begitu, Anda mendapatkan hasil yang waras meskipun Anda tidak menimpa pemeriksaan di setiap kueri. Sayangnya, sebagian besar (semua?) Sistem operasi tidak menyediakan lokal yang hanya bernama "Unicode default" atau sesuatu seperti itu, jadi Anda harus menebak dan / atau meneliti pilihan yang baik. Sebagai contoh, di Linux / glibc, lokal de_DE.utf8 atau en_US.utf8 cukup melewati perilaku default, jadi keduanya adalah pilihan yang baik.
Saya tidak berpikir menggunakan C locale adalah ide yang bagus, karena dengan itu perilaku default aplikasi Anda tidak akan berguna. Dan Anda mungkin tidak mendapatkan perilaku yang tepat dari operasi konversi kasus.
(Mengganti susunan dalam kueri tidak memiliki banyak overhead. Ini hanya operasi parse-waktu.)
sumber
utf8_unicode_ci
itulah cara yang harus dilakukan .Kami menggunakan postgres dalam wadah buruh pelabuhan, sehingga kami selalu memiliki ICU yang tersedia dan digunakan
und-x-icu
sebagai default.Ini disebutkan dalam bab 23.2.2.2.2. Kumpulan ICU dari dokumen-dokumen pos menyebutkan:
sumber