Haruskah Latin-1 digunakan lebih dari UTF-8 ketika datang ke konfigurasi database?

65

Kami menggunakan MySQL di perusahaan tempat saya bekerja, dan kami membangun aplikasi internal yang menghadap ke klien dan menggunakan Ruby on Rails.

Ketika saya mulai bekerja di sini, saya mengalami masalah yang belum pernah saya temui sebelumnya; database pada server produksi diatur ke Latin-1, yang berarti bahwa permata MySQL melempar pengecualian setiap kali ada input pengguna di mana pengguna menyalin & menempelkan karakter UTF-8.

Bos saya menyebut ini "karakter buruk" karena kebanyakan dari mereka adalah karakter yang tidak dapat dicetak, dan mengatakan bahwa kita perlu menghapusnya. Saya telah menemukan beberapa cara untuk melakukan ini, tetapi akhirnya kami berakhir dalam keadaan di mana karakter UTF-8 diperlukan. Plus itu agak merepotkan, terutama karena sepertinya satu-satunya solusi yang pernah saya baca untuk masalah ini adalah dengan hanya mengatur database ke UTF-8 (masuk akal bagi saya).

Satu-satunya argumen yang saya dengar untuk tetap menggunakan Latin-1 adalah bahwa memungkinkan karakter UTF-8 yang tidak dapat dicetak dapat mengacaukan pencarian teks / teks lengkap di MySQL. Apakah ini benar?

Apakah ada alasan lain seseorang harus menggunakan Latin-1 lebih dari UTF-8? Ini pemahaman saya bahwa itu lebih unggul dan menjadi lebih di mana-mana.

Ravenstine
sumber
4
@jon LATIN-1 bukan khusus Bahasa Inggris. Bahasa Spanyol terkandung dengan sempurna di sana, juga Prancis jika saya tidak salah.
Darkhogg
4
@Darkhog: Latin1 memang tidak spesifik untuk bahasa Inggris, tetapi pada dasarnya terbatas pada huruf Eropa-Eropa.
Bart van Ingen Schenau
16
Satu-satunya manfaat yang mungkin dari menggunakan Latin 1 daripada UTF-8 dalam sistem modern adalah sabotase. Tentu saja itu hanya bermanfaat bagi penyabot, dan siapa pun kesetiaannya, bukan untuk pemilik atau pengembang sistem.
Jon Hanna
13
Sayang sekali basis data Anda tidak akan bisa memegang simbol Euro, atau bahkan nama saya (דותן).
dotancohen
20
pengguna "menyalin dan menempel" karakter non-latin-1? jangan memperlakukan unicode sebagai beberapa hal sembrono yang tidak relevan yang hanya dipedulikan oleh kutu buku nakal. cukup banyak dari kita mengetik karakter yang tidak sesuai dengan latin-1 secara teratur - saya mendengar banyak orang berbicara bahasa non-Eropa, bahkan ♥
Eevee

Jawaban:

131

Unicode tentu sulit, dan pengkodean UTF-8 memiliki beberapa sifat tidak nyaman. Namun, UTF-8 telah menjadi pengkodean standar de-facto di web, melampaui ASCII, Latin-1, UCS-2 dan UTF-16. Cukup gunakan UTF-8 di mana-mana .

Alasan paling penting mengapa Anda harus mendukung Unicode adalah bahwa Anda tidak boleh membuat asumsi yang tidak perlu tentang input pengguna. Saya tidak tahu apa domain Anda, tetapi hal-hal seperti nama pengguna Ibrani, posting blog tentang China, komentar dengan Emoji, atau teks dengan gaya sederhana - seperti "ini" - harus dimungkinkan ... Oh, itu adalah tanda kutip yang benar secara tipografi ( “”alih-alih ""), tanda hubung en-wide, dan elipsis, yang merupakan karakter yang umum dalam teks bahasa Inggris, tetapi tidak didukung oleh ASCII atau Latin-1. Jadi tidak mendukung skrip lain bukan hanya masalah besar bagi Anda untuk budaya lain, tetapi berpegang pada Latin-1 bahkan tidak memungkinkan Anda untuk menulis bahasa Inggris dengan baik.

Gagasan bahwa Unicode hanya memungkinkan "karakter buruk" salah. Ya, teks sangat rumit, dan Unicode tidak akan menyembunyikannya dari Anda. Bos Anda mungkin berpikir tentang karakter yang dikomposisikan, di mana satu basis codep seperti adimodifikasi oleh codepoint berikutnya yang misalnya mewakili diakritik untuk membentuk satu karakter visual seperti á. Ini tidak benar-benar menghalangi jalan Anda ketika mencoba melakukan pencarian jika Anda melakukan semacam normalisasi. Misalnya, Anda dapat menyimpan semua teks dalam bentuk NFC yang menciutkan komposisi tersebut ke dalam bentuk prekomposisikannya jika tersedia. Saat melakukan pencarian, Anda juga dapat menghapus semua karakter penulisan dari teks, tetapi ini dapat secara substansial mengubah artinya dalam beberapa bahasa.

Unicode juga menambahkan banyak karakter yang tidak patut dicetak - tetapi bahkan ASCII memiliki banyak karakter. Apakah Anda akan menangani NUL di tengah-tengah string? Bagaimana dengan 0x1C, "File Separator"? Saya belum pernah melihat setengah dari itu . Latin-1 menambahkan tanda hubung lembut yang menunjukkan peluang kata break, tetapi sebaliknya tidak terlihat. Apakah itu juga merusak pencarian teks lengkap Anda? Dengan kata lain, bahkan ASCII dan Latin-1 memungkinkan Anda untuk sepenuhnya menghancurkan input Anda jika Anda menganggap itu semua hanya teks yang dapat dicetak!

amon
sumber
8
Dari perspektif basis data, beberapa karakter tersebut tidak / tidak boleh diizinkan dalam bidang jenis teks (teks / varchar / char / dll.). MySQL memang mengizinkan karakter nol dalam tipe data ini, tetapi database lain seperti PostgreSQL tidak. Anda seharusnya menggunakan BLOB (MySQL) atau BYTEA (PostgreSQL) jika Anda ingin dapat menyimpan karakter tersebut.
cimmanon
15
"Menempel ke Latin-1 bahkan tidak memungkinkan Anda untuk menulis bahasa Inggris yang baik" Itu hal yang baik, jika tidak, kode unik akan ditentang lebih kuat. ;-)
Deduplicator
3
@ PaŭloEbermann Embedded NUL karakter berarti data Anda adalah gumpalan biner, bukan hanya string. NUL adalah contoh yang aneh, karena saya percaya UTF-8 menghindari penggunaan \0byte sebagai bagian dari multi-byte encoding, untuk memastikan kode non-UTF8-aware tidak berhenti di tengah-tengah string.
Peter Cordes
7
Semua karakter unicode dapat dicetak - Anda hanya perlu font yang benar :-)
James Anderson
4
@JamesAnderson, fontnya akan salah dan rusak. en.wikipedia.org/wiki/Unicode_control_characters
djechlin
62

Saya pikir di luar pertanyaan teknis, bos Anda mungkin tidak punya waktu untuk mengikuti perkembangan standar saat ini.

Karena sikapnya tidak sepenuhnya makan siang, hanya ketinggalan zaman, hormati posisinya ketika membahas masalah ini (dan Anda harus ingat untuk berdiskusi , tidak berdebat), dan mencoba untuk mengatasi masalah yang ia miliki terkait dengan UTF-8. Saya menduga masalah mendasar bukanlah masalah teknis dan mungkin memerlukan beberapa tingkat negosiasi soft-skill.

Nelson
sumber
6
Saya tidak bisa menyetujui lebih banyak. Sebenarnya saya menyesal bahwa dalam jawaban saya sendiri saya sepenuhnya mengabaikan "sisi manusia", yang dalam masalah ini mungkin sangat penting. Seandainya aku bisa memilih lebih dari satu kali :-)
LSerni
2
memanggil segala sesuatu di luar dari latin-1 bad characterdan berpikir ini non-printableadalah just out-dateduntuk Anda?
njzk2
2
Masalah sebenarnya adalah, "Apakah ini masalah teknis yang sedang kita hadapi?" Saya tidak percaya bos OP pergi ke sekolah dan diajarkan ini, atau membaca beberapa manual teknis / jurnal dan sampai pada kesimpulan itu. Saya tidak mengerti bahwa solusinya adalah solusi teknis. Ironisnya, komentar tersebut menunjukkan inti permasalahan; mengatasi masalah ini bisa sangat ofensif jika dilakukan dengan tidak benar.
Nelson
49

Siapakah di antara kita yang benar?

Sekali waktu, bosmu adalah. Tetapi seiring berjalannya waktu, banyak hal berubah. Saat ini, Anda (tetapi sebelum berlari ke bos Anda, pastikan untuk membaca jawaban Nelson juga ).

Versi lama MySQL, dan versi lama sebagian besar semuanya , ditangani jauh lebih baik dengan Latin1 / ISO-8859-1 (5) yang lebih tua daripada UTF8.

Ada alasan mengapa UTF8 telah dibuat, dikembangkan, dan didorong sebagian besar di mana-mana: jika diimplementasikan dengan benar, ia bekerja jauh lebih baik . Ada beberapa masalah kinerja dan penyimpanan yang berasal dari fakta bahwa karakter Latin1 adalah 8 bit, sedangkan karakter UTF8 mungkin dari 8 hingga 32 bit. Jadi, ketika merencanakan VARCHARAnda perlu mempertimbangkan ini. Dan rutinitas pencarian Anda akan sedikit lebih lambat. Mereka akan dapat melakukan lebih banyak hal (mis. Pencarian dengan kepekaan aksen atau tanpa . Tidak dapat melakukannya dalam bahasa Latin1 tanpa kerja yang luas), tetapi mereka akan membutuhkan waktu lebih lama.

Tetapi di sisi lain, penyimpanannya murah , overhead realistis pada ukuran file kurang dari 2-3%, daya komputasi juga murah dan semakin murah sesuai dengan Hukum Moore; sementara waktu dan harapan pelanggan Anda jelas tidak .

Anda mungkin harus khawatir untuk alat pencarian dll. Jika Anda adalah orang yang mengembangkan alat tersebut. Tetapi Anda mungkin tidak. Anda menggunakan alat-alat itu; bahkan mereka yang tidak sepenuhnya mematuhi UTF8 kemarin (seperti MySQL sebelumnya tidak), hari ini, atau akan segera (mis. MySQL dengan dukungan utf8mb4).

Jadi dengan hati-hati merencanakan dan mengimplementasikan UTF8 dengan cara yang benar ( tidak menampar Latin1 sebagai setelahnya) Anda dapat memiliki kode yang sangat masuk akal di masa depan , yang, jika Anda berencana untuk pernah melakukan bisnis dengan negara Asia, adalah Sangat Bagus Benda. Dan jika Anda tidak memiliki rencana seperti itu, orang lain akan memilikinya, dan orang-orang itu bisa menjadi pelanggan, pemasok, atau mitra Anda.

Jadi ketika mereka mulai mengirimi Anda data UTF8, Anda harus mengatur hal yang rumit untuk dikonversi ke sana-sini Latin1, dan menangani kasus-kasus yang tidak dapat diselesaikan.

Ketika Anda memperhitungkan anggaran, biaya beberapa pertempuran kecil melawan ninja mojibake jahat , dan menganggap bahwa mereka tidak akan pergi - seperti yang sudah Anda temukan - maka Anda akan menyadari bahwa pergi UTF8 tidak hanya lebih sederhana, itu akan menjadi lebih murah juga.

LSerni
sumber
4

Beberapa situasi di mana membatasi karakter yang ditetapkan hanya untuk ASCII mungkin masuk akal adalah untuk bidang pilihan terbatas, misalnya bidang status, karena Anda benar-benar mengontrol nilai-nilai yang dapat ada, dan kunci asing / referensi ke sistem eksternal, karena jarang ada alasan untuk mereka memiliki apa pun selain karakter alfanumerik dan beberapa simbol.

Untuk teks lain, cukup gunakan UTF-8.

Lie Ryan
sumber
2
Bukankah MySQL punya enum?
raptortech97
2
Dan karena ASCII adalah bagian dari UTF8, cukup gunakan UTF8 bahkan kemudian.
RemcoGerlich
@RemcoGerlich: Saya tidak setuju bahwa Anda bisa menggunakan UTF8 untuk itu. Dalam pandangan saya, referensi eksternal bukanlah teks melainkan urutan byte yang buram. Mereka tidak memiliki charset kecuali untuk kenyamanan notasi. Jika urutan byte memiliki interpretasi dalam charset tertentu, itu adalah sistem eksternal atau domain aplikasi, bukan database.
Lie Ryan
3
@ LieRyan: Saya melihat hal itu, tapi kemudian tidak boleh ASCII juga, mungkin beberapa format gumpalan biner atau lebih.
RemcoGerlich
3

Untuk memulai dengan jawabannya, tidak masalah, bagaimana server Anda dikonfigurasi. Pengkodean karakter dalam MySQL dapat dikonfigurasikan per-kolom (artinya, tabel yang sama dapat menampung karakter dalam beberapa pengkodean, mudah). Yaitu server saya (dan sejumlah database lama di dalamnya) dikonfigurasikan untuk cp1251 secara default untuk klien lama yang tidak dapat mengatur pemeriksaan yang benar saat terhubung (klien perangkat keras berbeda), tetapi basis data utama dalam produksi semuanya menggunakan UTF-8.

Berbicara tentang "ruang terbuang" - Anda tidak dapat secara realistis menyebut data penting sebagai pemborosan, bukan? Namun, peningkatan ruang penyimpanan akan berbeda tergantung pada bahasa tempat data Anda. Dari tidak signifikan (kurang dari 1%) meningkat jika situs Anda terutama dalam bahasa Inggris dan hingga 100%, jika sebagian besar menggunakan karakter di luar rentang ASCII . Dan bahkan lebih, jika Anda bergerak ke timur. Kemudian spesifikasi UTF-8 (disebut UTF8mb4) memungkinkan hingga 4 byte per titik kode.

Dan untuk "siapa yang benar" ... Sebenarnya, ini adalah pertanyaan sosial lebih dari itu teknis. Mungkin ada alasan yang valid untuk pengaturan server tertentu, tetapi Anda harus tahu implikasinya. Tetapi jika Anda bertanya kepada saya, tidak ada alasan untuk tidak menggunakan UTF-8. Ini adalah satu-satunya jenis aturan semua teks di dunia.

AnrDaemon
sumber
MySQL akan mencoba untuk mengubah data dalam pengkodean basis data sebelum mengubahnya menjadi pengkodean kolom. Jika Anda memiliki klien utf8, database latin1, dan kolom utf8, maka data teks dapat hilang.
Ivan Solntsev
Ivan, itu pertanyaan yang sama sekali berbeda. Interaksi antara karakter-set-klien, karakter-set-server, karakter-set-koneksi, karakter-set-hasil adalah artikel panjang dalam dokumentasi MySQL. Dan dalam hal pengaturan susunan kolom per, "susunan basis data" adalah susunan kolom, dan secara langsung dikonversi ke karakter-set-hasil, mengabaikan susunan basis data.
AnrDaemon
0

Cukup jelaskan kepadanya bahwa UTF-8 adalah standar untuk lalu lintas web. Dan setiap pengguna dapat memasukkan karakter unicode yang valid di browser mereka.

Ini jauh lebih mudah untuk memiliki utf-8 / unicode sepanjang jalan dari ujung depan ke ujung belakang daripada berurusan dengan banyak dan berbagai masalah yang dihasilkan dari utf-8-> latin-1-> utf-8.

James Anderson
sumber