Antara utf8_general_ci
dan utf8_unicode_ci
, apakah ada perbedaan dalam hal kinerja?
Dua collations yang baik untuk karakter UTF-8 encoding. Perbedaan dalam cara teks disusun dan dibandingkan.
Catatan: Anda harus menggunakan utf8mb4
daripada utf8
. Mereka berdua rujuk ke UTF-8 encoding, tetapi yang lebih tua utf8
telah MySQL-batasan tertentu mencegah penggunaan karakter bernomor atas 0xFFFD.
Catatan: versi Baru dari MySQL telah diperbarui Unicode aturan pengurutan, tersedia di bawah nama-nama seperti utf8mb4_0900_ci
untuk aturan berdasarkan Unicode 9.0 - dan dengan tidak setara umum
varian.
Perbedaan utama
utf8mb4_unicode_ci
adalah berdasarkan hasil resmi Unicode aturan untuk universal penyortiran dan perbandingan, yang macam akurat dalam berbagai bahasa. utf8mb4_general_ci
adalah satu set sederhana dari aturan pengurutan yang bertujuan untuk melakukan serta dapat saat mengambil banyak potongan pendek yang dirancang untuk meningkatkan kecepatan. Tidak mengikuti aturan Unicode dan akan mengakibatkan tidak diinginkan sorting atau perbandingan dalam beberapa situasi, seperti ketika menggunakan bahasa tertentu atau karakter.
Modern server, hal ini meningkatkan kinerja akan semua tapi diabaikan. Itu dirancang dalam waktu ketika server memiliki sebagian kecil dari kinerja CPU dari hari ini's komputer.
Catatan: tidak ada sekarang versi terbaru dari utf8mb4_unicode_ci
disebut utf8mb4_0900_ai_ci
- ini didasarkan pada perubahan dalam Unicode versi 9.0, dan juga ternyata lebih cepat. Itu mengadopsi skema penamaan baru dimana 0900
adalah versi Unicode dan ai
berarti aksen-sensitif - seperti sebelumnya utf8mb4_unicode_ci
, aksen dalam huruf tidak dianggap signifikan.
Manfaat dari utf8mb4_unicode_ci
atas utf8mb4_general_ci
utf8mb4_unicode_ci
, yang menggunakan Unicode aturan untuk menyortir dan perbandingan, mempekerjakan cukup kompleks algoritma untuk penyortiran yang benar dalam berbagai bahasa dan kapan menggunakan berbagai macam karakter khusus. Aturan ini perlu untuk memperhitungkan bahasa-konvensi tertentu; tidak semua orang macam karakter mereka dalam apa yang kita sebut 'urutan abjad'.
Sejauh Latin (ie "Eropa") bahasa yang pergi, tidak ada banyak perbedaan antara Unicode penyortiran dan modern utf8mb4_general_ci
sorting di MySQL, tapi masih ada beberapa perbedaan: utf8mb4_general_ci
macam mereka sebagai karakter tunggal (mungkin seperti "s" dan "e" masing-masing). utf8mb4_unicode_ci
menangani ini dengan baik.
Dalam bahasa non-latin, seperti bahasa-bahasa Asia atau bahasa dengan huruf yang berbeda, mungkin ada banyak lebih perbedaan antara Unicode penyortiran dan modern utf8mb4_general_ci
penyortiran. Kesesuaian utf8mb4_general_ci
akan sangat bergantung pada bahasa yang digunakan. Untuk beberapa bahasa, it'akan cukup memadai.
Apa yang harus anda gunakan?
Ada hampir pasti tidak ada alasan untuk menggunakan utf8mb4_general_ci
lagi, seperti yang kita telah meninggalkan titik di mana kecepatan CPU ini cukup rendah sehingga perbedaan kinerja akan menjadi penting. Database anda akan hampir pasti akan dibatasi oleh hambatan lain dari ini.
Di masa lalu, beberapa orang dianjurkan untuk menggunakan utf8mb4_general_ci
kecuali bila akurat penyortiran akan menjadi cukup penting untuk membenarkan biaya kinerja. Hari ini, bahwa biaya kinerja yang telah semua tetapi menghilang, dan pengembang mengobati internasionalisasi yang lebih serius.
Ada's sebuah argumen dapat dibuat bahwa jika kecepatan lebih penting bagi anda daripada akurasi, anda dapat juga melakukan pengurutan pada semua. It's sepele untuk membuat suatu algoritma yang lebih cepat jika anda tidak perlu untuk menjadi akurat. Jadi, utf8mb4_general_ci
adalah kompromi yang's mungkin tidak diperlukan untuk kecepatan alasan dan mungkin juga tidak cocok untuk akurasi alasan.
Satu hal lain yang saya'll tambahkan adalah bahwa bahkan jika anda tahu aplikasi anda hanya mendukung bahasa inggris, mungkin masih perlu berurusan dengan orang-orang's nama, yang sering dapat mengandung karakter yang digunakan dalam bahasa-bahasa lain di mana hal itu sama penting untuk mengurutkan dengan benar. Menggunakan Unicode aturan untuk segala sesuatu yang membantu menambah ketenangan pikiran yang sangat cerdas Unicode orang-orang yang telah bekerja sangat keras untuk membuat pengurutan bekerja dengan baik.
Apa bagian yang berarti
Pertama, ci
adalah untuk case-sensitive sortasi dan perbandingan. Ini berarti's cocok untuk data tekstual, dan hal ini tidak penting. Jenis lain dari pemeriksaan ini adalah cs
(case-sensitive) untuk data tekstual mana hal ini penting, dan bin
, dimana pengkodean harus sesuai, bit, bit, yang lebih cocok untuk bidang yang benar-benar dikodekan data biner (termasuk, misalnya, Base64). Kasus-sensitif sorting menyebabkan beberapa hasil yang aneh dan kasus-sensitif perbandingan dapat mengakibatkan nilai-nilai duplikat hanya berbeda dalam kasus surat, sehingga kasus-sensitif collations yang jatuh dari nikmat untuk data tekstual - jika hal ini penting bagi anda, maka jika tidak dapat diketahui tanda baca dan sebagainya mungkin juga signifikan, dan biner pemeriksaan mungkin akan lebih tepat.
Berikutnya, unicode
atau umum
mengacu pada spesifik penyortiran dan perbandingan aturan - khususnya, cara teks normal atau dibandingkan. Ada banyak set yang berbeda dari aturan untuk utf8mb4 pengkodean karakter, dengan unicode
dan umum
menjadi dua yang mencoba untuk bekerja dengan baik dalam semua bahasa yang mungkin lebih dari satu tertentu. Perbedaan antara dua set dari aturan ini adalah subjek dari jawaban ini. Perhatikan bahwa unicode
menggunakan aturan dari Unicode 4.0. Versi terbaru dari MySQL tambahkan mengetahui aturan unicode_520
menggunakan aturan dari Unicode 5.2, dan 0900
(menjatuhkan "unicode_" bagian) menggunakan aturan-aturan dari Unicode 9.0.
Dan terakhir, utf8mb4
tentu saja pengkodean karakter yang digunakan secara internal. Dalam jawaban ini saya'm hanya berbicara tentang Unicode berdasarkan pengkodean.Aku ingin tahu apa perbedaan kinerja antara menggunakan utf8_general_ci
dan utf8_unicode_ci
, tapi aku tidak menemukan apapun tolok ukur yang tercantum di internet, jadi saya memutuskan untuk membuat tolok ukur sendiri.
Saya membuat sebuah tabel yang sangat sederhana dengan 500.000 baris:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Kemudian saya mengisinya dengan data acak dengan menjalankan prosedur ini disimpan:
CREATE PROCEDURE randomizer()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE random CHAR(20) ;
theloop: loop
SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
INSERT INTO test VALUES (i+1, random);
SET i=i+1;
IF i = 500000 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END
Kemudian saya dibuat disimpan prosedur berikut untuk patokan sederhana PILIH
, PILIH
dengan LIKE
, dan sorting (PILIH
dengan ORDER BY
):
CREATE PROCEDURE benchmark_simple_select()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description = 'test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_select_like()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description LIKE '%test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_order_by()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
SET i = i + 1;
IF i = 10 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
Dalam prosedur yang disimpan di atas utf8_general_ci
pemeriksaan digunakan, tapi tentu saja selama tes saya digunakan baik utf8_general_ci
dan utf8_unicode_ci
.
Aku menelepon masing-masing disimpan prosedur 5 kali untuk masing-masing pemeriksaan (5 kali untuk utf8_general_ci
dan 5 kali untuk utf8_unicode_ci
) dan kemudian dihitung nilai rata-rata.
Hasil saya:
benchmark_simple_select()
utf8_general_ci
: 9,957 ms utf8_unicode_ci
: 10,271 ms Dalam penghitungan ini menggunakan utf8_unicode_ci
lebih lambat dari utf8_general_ci
3,2%.
benchmark_select_like()
utf8_general_ci
: 11,441 ms utf8_unicode_ci
: 12,811 ms Dalam penghitungan ini menggunakan utf8_unicode_ci
lebih lambat dari utf8_general_ci
sebesar 12%.
benchmark_order_by()
utf8_general_ci
: 11,944 ms utf8_unicode_ci
: 12,887 ms Dalam penghitungan ini menggunakan utf8_unicode_ci
lebih lambat dari utf8_general_ci
sebesar 7,9%.
Post ini menjelaskan dengan sangat baik.
Singkatnya: utf8_unicode_ci menggunakan Unicode Algoritma Pemeriksaan sebagaimana didefinisikan dalam standar Unicode, sedangkan utf8_general_ci yang lebih sederhana urutan yang menghasilkan "kurang akurat" penyortiran hasil.
Lihat mysql manual, Set Karakter Unicode bagian:
Untuk setiap set karakter Unicode, operasi dilakukan dengan menggunakan _general_ci pemeriksaan yang lebih cepat daripada mereka untuk _unicode_ci pemeriksaan. Untuk contoh, perbandingan untuk utf8_general_ci pemeriksaan lebih cepat, tapi sedikit kurang benar, dari perbandingan untuk utf8_unicode_ci. Yang alasan untuk ini adalah bahwa utf8_unicode_ci mendukung pemetaan tersebut sebagai ekspansi; itu adalah, ketika salah satu membandingkan karakter sebagai sama dengan kombinasi dari karakter lain. Untuk contoh, di jerman dan beberapa lainnya bahasa "ß" sama dengan "ss". utf8_unicode_ci juga mendukung kontraksi dan dapat diketahui karakter. utf8_general_ci adalah warisan pemeriksaan yang tidak mendukung ekspansi, kontraksi, atau tidak dapat diketahui karakter. Ini dapat membuat hanya satu-ke-satu perbandingan antara karakter.
Jadi untuk meringkas, utf_general_ci menggunakan yang lebih kecil dan kurang benar (sesuai standar) set perbandingan dari utf_unicode_ci yang harus ** menerapkan seluruh standar. Yang general_ci set akan lebih cepat karena ada sedikit perhitungan yang harus dilakukan.
Dalam kata-kata singkat:
Jika anda membutuhkan baik pengurutan menggunakan utf8_unicode_ci
(ini adalah metode yang disukai),
tetapi jika anda benar-benar tertarik pada kinerja - penggunaan utf8_general_ci
, tapi tahu bahwa itu adalah sedikit usang.
Perbedaan dalam hal kinerja yang sangat sedikit.
Seperti yang bisa kita baca di sini (Peter Gulutzan) ada perbedaan pada sorting/membandingkan cat huruf "Ł" (L dengan stroke - html esc: Ł
) (lower case: "ł" - html esc: ł
) - kami memiliki asumsi berikut:
utf8_polish_ci Ł greater than L and less than M
utf8_unicode_ci Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci Ł greater than Z
Dalam bahasa polandia huruf Ł
setelah huruf L
dan sebelum M
. Tidak ada salah satu dari coding ini lebih baik atau lebih buruk - itu tergantung dari kebutuhan anda.
Menurut posting ini, ada sangat besar manfaat kinerja pada MySQL 5.7 ketika menggunakan utf8mb4_general_ci dalam manfaat dari utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact-on-mysql-performance/