PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Susunan yang lebih kuat dengan dukungan ICU di PostgreSQL 10

Dalam artikel ini, saya ingin memperkenalkan dukungan ICU di PostgreSQL, yang telah saya kerjakan untuk PostgreSQL versi 10, yang akan muncul akhir tahun ini.

Penyortiran

Penyortiran adalah fungsi penting dari sistem basis data. Pertama, pengguna umumnya ingin melihat data yang diurutkan. Hasil kueri apa pun yang berisi lebih dari satu baris dan ditujukan untuk konsumsi pengguna akhir mungkin ingin diurutkan, hanya untuk pengalaman pengguna yang lebih baik. Kedua, banyak fungsi internal sistem database bergantung pada pengurutan data atau ketersediaan data yang diurutkan. Indeks B-tree adalah contoh yang jelas. Indeks BRIN memiliki pengetahuan tentang urutan. Partisi rentang harus membandingkan nilai. Gabungkan gabungan bergantung pada input yang diurutkan. Gagasan yang umum untuk teknik yang berbeda ini adalah, secara kasar, jika Anda telah mengurutkan data dan Anda tahu apa yang Anda cari, itu membuatnya lebih cepat untuk menemukan tempat di mana data itu seharusnya ditemukan.

Ada dua aspek penting untuk menyortir. Salah satunya adalah algoritma pengurutan. Ini adalah topik standar dalam ilmu komputer, dan banyak pekerjaan telah dilakukan di PostgreSQL selama bertahun-tahun untuk menyempurnakan berbagai algoritma dan metode penyortiran, tetapi bukan itu yang akan saya tulis. Yang lain adalah memutuskan dalam urutan apa hal-hal itu seharusnya, yang kita sebut collation. Dalam banyak kasus, pilihan itu jelas. 1 datang sebelum 2. SALAH datang sebelum BENAR … yah, seseorang hanya secara sewenang-wenang memutuskan yang itu. A biasanya muncul sebelum B. Tetapi ketika berbicara tentang teks bahasa alami, semuanya menjadi menarik. Ada banyak cara berbeda untuk mengurutkan teks, dan metode sebenarnya untuk menyusun string teks lebih rumit daripada yang terlihat. Bahasa yang berbeda lebih menyukai urutan pengurutan yang berbeda, tetapi bahkan dalam suatu bahasa, mungkin ada variasi untuk aplikasi yang berbeda. Dan ada detail yang perlu dikhawatirkan, seperti apa yang harus dilakukan tentang spasi, tanda baca, perbedaan huruf besar/kecil, tanda diakritik, dan sebagainya. Cari Algoritma Collation Unicode untuk wawasan lebih lanjut tentang ini.

Sebelum fitur ICU dicommit, semua fungsi ini difasilitasi oleh library C di sistem operasi. PostgreSQL pada dasarnya hanya meneruskan string ke strcmp() , strcoll() , dan sejenisnya dan bekerja dengan hasilnya. Pustaka C di berbagai sistem operasi mengimplementasikan berbagai varian dan nuansa susunan yang disebutkan di atas ke tingkat fungsionalitas dan kualitas yang berbeda, sehingga PostgreSQL dapat melakukan apa yang dapat dilakukan oleh sistem operasi Anda.

Mengubah susunan

Masalah dimulai jika sistem operasi perlu mengubah susunan yang disediakannya. Mengapa mereka ingin melakukan itu? Bisa jadi susunan sebelumnya salah dan harus diperbaiki. Mungkin standar baru untuk suatu bahasa diterbitkan dan susunannya akan diperbarui untuk itu. Mungkin representasi internal dari collation dan data string diubah karena alasan kinerja atau karena itu perlu untuk mengimplementasikan fungsionalitas tambahan. Untuk banyak program, ini bukan masalah. Anda mungkin hanya melihat output yang dipesan sedikit berbeda, jika Anda melihat perbedaan sama sekali. Untuk sistem database, bagaimanapun, ini adalah masalah besar. Seperti dijelaskan di atas, PostgreSQL menyimpan data yang diurutkan dalam indeks dan tempat lain dan bergantung pada urutan pengurutan agar benar. Jika urutan pengurutan tidak benar, pencarian indeks mungkin tidak menemukan data yang sebenarnya ada. Atau menulis ke indeks akan menulis ke tempat yang berbeda. Atau data ditulis atau dibaca dari partisi yang salah. Hal ini dapat menyebabkan kesalahan duplikat data atau munculnya kehilangan data karena data tidak berada di tempat yang dicari. Dengan kata lain, ini dapat menyebabkan kerusakan data dan (tampaknya) kehilangan data.

Sayangnya, sejauh ini kami tidak bisa berbuat banyak. Sistem operasi memperbarui susunannya kapan pun mereka mau, mungkin sebagai bagian dari peningkatan ke paket pustaka C mereka. Tidak ada cara untuk mengetahui hal ini dengan cara yang masuk akal, atau mungkin dengan memeriksa paket pembaruan secara detail. Dan bahkan kemudian, apakah Anda akan menolak pembaruan penting dari pustaka C Anda karena Anda memperhatikan bahwa susunan di beberapa lokal yang tidak Anda gunakan telah diubah? Itu adalah situasi yang sangat tidak nyaman.

Masuk ICU

Jadi di mana ICU masuk? ICU, International Components for Unicode, adalah library yang menyediakan fasilitas internasionalisasi dan lokalisasi, termasuk collation. Jadi dalam hal itu, ini adalah alternatif untuk menggunakan fasilitas di perpustakaan C standar. Hal yang menyenangkan adalah bahwa ICU secara eksplisit memberikan beberapa jaminan tentang stabilitas pemeriksaan:

  • Kolasi tidak akan diubah dengan cara yang tidak kompatibel sebagai bagian dari pembaruan rilis kecil.
  • Pengumpulan memiliki versi, yang dapat diperiksa, dan bila susunan berubah dengan cara yang tidak kompatibel, versi akan berubah.

Untuk pengguna PostgreSQL, ini berarti dalam praktiknya:

  • Pembaruan paket sistem operasi rutin tidak akan mengganggu validitas data yang diurutkan. Sejak postgres biner ditautkan ke versi utama libicu , pemutakhiran paket sistem operasi rutin tidak akan berakhir dengan postgres ditautkan ke versi utama baru libicu , selama a) Anda tidak memperbarui paket PostgreSQL, atau b) paket PostgreSQL masih ditautkan ke versi utama ICU yang sama seperti sebelumnya. Pengemas harus berhati-hati untuk mempertahankan ini dengan benar, tetapi praktiknya seharusnya tidak terlalu bermasalah.
  • Saat paket utama dan pemutakhiran sistem operasi mengubah versi susunan, kami memiliki cara untuk mendeteksinya dan memperingatkan pengguna. Saat ini kami hanya memperingatkan dan menawarkan beberapa panduan dan alat untuk memperbaiki berbagai hal, tetapi di masa mendatang kami mungkin akan menyempurnakan dan mengotomatiskan ini lebih lanjut.

(Untuk membuatnya lebih eksplisit bagi pembuat paket:Di cabang sistem operasi Anda yang stabil, Anda tidak boleh mengubah versi ICU utama yang ditautkan dengan set paket PostgreSQL tertentu.)

Menggunakan ICU

Untuk dapat menggunakan ini, PostgreSQL perlu dibangun secara eksplisit dengan dukungan ICU. Saat membangun dari sumber, gunakan ./configure --with-icu bersama dengan pilihan lain yang diinginkan. Kami berharap sebagian besar paket biner utama juga menawarkan ini secara default. Ketika ini selesai, koleksi berbasis ICU ditawarkan bersama dengan koleksi berbasis libc yang ditawarkan rilis sebelumnya. (Jadi membangun dengan dukungan ICU tidak menghapus dukungan pemeriksaan libc; keduanya ada bersama-sama.) Periksa dokumentasi untuk detail tentang cara memilih pemeriksaan berbasis ICU versus yang berbasis libc. Misalnya, jika sebelumnya Anda telah menentukan

CREATE TABLE ... (... x text COLLATE "en_US" ...)

sekarang Anda mungkin melakukannya

CREATE TABLE ... (... x text COLLATE "en-x-icu" ...)

Ini akan memberi Anda perilaku yang terlihat oleh pengguna yang kira-kira sama seperti sebelumnya, kecuali bahwa database Anda akan lebih tahan masa depan dalam hal peningkatan. (Di Linux/glibc, urutan pengurutan sebagian besar harus sama, tetapi mungkin ada sedikit perbedaan dalam beberapa detail. Namun, jika Anda menggunakan sistem operasi yang pustaka C-nya tidak mendukung pengumpulan Unicode sama sekali, seperti macOS atau versi FreeBSD yang lebih lama, maka ini akan menjadi perubahan besar — ​​menjadi lebih baik.)

Saat ini, dukungan ICU hanya tersedia untuk pemeriksaan yang ditentukan secara eksplisit. Susunan default dalam database masih selalu disediakan oleh pustaka C. Mengatasi ini adalah proyek masa depan.

Jika Anda meningkatkan basis data seperti itu dengan pg_upgrade misalnya ke instalasi PostgreSQL baru yang ditautkan dengan versi utama ICU yang lebih baru yang telah mengubah versi pemeriksaan dari pemeriksaan yang Anda gunakan, maka Anda akan mendapatkan peringatan dan harus memperbaiki misalnya indeks apa pun yang bergantung pada pemeriksaan. Petunjuk untuk ini juga ada di dokumentasi.

Kunci yang disingkat

Jadi perubahan ini akan memberikan beberapa perbaikan yang sangat penting untuk ketahanan jangka panjang dari sistem database. Tetapi ICU juga merupakan peningkatan dari sistem perpustakaan C di area lain.

Misalnya, PostgreSQL B-trees dapat menyimpan apa yang disebut kunci yang disingkat untuk meningkatkan kinerja dan penyimpanan. Untuk tipe data string teks, dengan pustaka C standar, kami akan menghitung kunci yang disingkat ini menggunakan strxfrm() fungsi. Namun, kami telah mengetahui bahwa banyak pustaka C memiliki berbagai bug dan perilaku buruk yang membuat pendekatan ini tidak dapat diandalkan. Jadi optimasi kunci yang disingkat saat ini dinonaktifkan untuk tipe data string. Dengan ICU, kami dapat menggunakan panggilan API yang setara dan menghitung kunci yang disingkat dengan cara yang kami yakini sebagai cara yang andal dan stabil. Jadi ada kemungkinan peningkatan kinerja dari langkah ini juga.

Lebih banyak koleksi

Terlepas dari peningkatan ketangguhan dan kinerja internal ini, ada juga beberapa fungsi baru untuk pengguna.

Untuk beberapa bahasa, lebih dari satu urutan pengurutan mungkin relevan dalam praktik. (Ini mungkin membantu Anda memulai.) Salah satu contohnya adalah untuk bahasa Jerman, ada urutan pengurutan standar yang digunakan untuk sebagian besar tujuan dan urutan pengurutan "buku telepon" yang digunakan untuk daftar nama. Pustaka C standar hanya menyediakan salah satu dari varian tersebut (mungkin yang pertama). Tetapi jika Anda ingin menulis aplikasi yang mengurutkan dengan benar, misalnya, nama produk dan nama pelanggan, Anda harus dapat menggunakan keduanya.

Misalnya, contoh dari Wikipedia bahasa Jerman sekarang dapat direproduksi dengan PostgreSQL:

CREATE TABLE names (name text);

INSERT INTO names
    VALUES ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz');

=> SELECT name FROM names ORDER BY name COLLATE "de-u-co-standard-x-icu";
   name
----------
 Göbel
 Goethe
 Goldmann
 Göthe
 Götz

=> SELECT name FROM names ORDER BY name COLLATE "de-u-co-phonebk-x-icu";
   name
----------
 Göbel
 Goethe
 Göthe
 Götz
 Goldmann

=> SELECT name FROM names ORDER BY name COLLATE "de-AT-u-co-phonebk-x-icu";
   name
----------
 Goethe
 Goldmann
 Göbel
 Göthe
 Götz

(Dengan glibc, COLLATE "de_DE" dan COLLATE "de_AT" memang mengembalikan pesanan pertama.)

Salah satu cara menarik untuk menggabungkan beberapa fitur mungkin menggunakan domain untuk memodelkan perbedaan yang disebutkan di atas antara nama produk dan nama pelanggan:

CREATE DOMAIN product_name AS text COLLATE "de-u-co-standard-x-icu";
CREATE DOMAIN person_name AS text COLLATE "de-u-co-phonebk-x-icu";

(Ini hanya sebuah contoh. Tentu saja Anda juga dapat melampirkan COLLATE klausa ke definisi kolom secara langsung atau gunakan dalam kueri.)

Lebih banyak lagi koleksi

Akhirnya, dan ini jelas yang telah ditunggu-tunggu oleh dunia, sekarang ada cara untuk menyortir emoji dengan benar. Ini penting untuk memastikan bahwa semua wajah kucing Anda dalam urutan yang benar. Bandingkan

=# SELECT chr(x) FROM generate_series(x'1F634'::int, x'1F644'::int) AS _(x)
       ORDER BY chr(x) COLLATE "und-x-icu";
 chr
-----
 😴
 😵
 😶
 😷
 😸
 😹
 😺
 😻
 😼
 😽
 😾
 😿
 🙀
 🙁
 🙂
 🙃
 🙄

dengan

=# CREATE COLLATION "und-u-co-emoji-x-icu" (provider = icu, locale = 'und-u-co-emoji');
=# SELECT chr(x) FROM generate_series(x'1F634'::int, x'1F644'::int) AS _(x)
       ORDER BY chr(x) COLLATE "und-u-co-emoji-x-icu";
 chr
-----
 🙂
 🙃
 😶
 🙄
 😴
 😷
 😵
 🙁
 😺
 😸
 😹
 😻
 😼
 😽
 🙀
 😿
 😾

Ya, sebenarnya ada standar tentang ini.

Lebih banyak lagi yang akan datang

Ini baru permulaan. ICU menawarkan banyak fungsi di area ini yang belum kami paparkan melalui PostgreSQL. Ada opsi untuk penyortiran peka huruf besar/kecil, penyortiran tidak peka aksen, dan menyesuaikan susunan secara total. Cari yang di rilis PostgreSQL mendatang.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penggabungan Koneksi dengan Pgbouncer di PostgreSQL 9.0

  2. Bagaimana saya bisa menetapkan batas ukuran untuk tipe data int di PostgreSQL 9.5

  3. Cara Menyebarkan PostgreSQL ke Wadah Docker Menggunakan ClusterControl

  4. Pilih stempel waktu hari ini saja (sejak tengah malam)

  5. Fungsi dengan kueri SQL tidak memiliki tujuan untuk data hasil