Pertanyaan Apa perbedaan antara utf8_general_ci dan utf8_unicode_ci


Antara utf8_general_ci dan utf8_unicode_ci, apakah ada perbedaan dalam hal kinerja?


826
2018-04-20 03:43


asal


Jawaban:


Kedua kolasi ini keduanya untuk pengkodean karakter UTF-8. Perbedaannya adalah bagaimana teks diurutkan dan dibandingkan.

Catatan: Sejak MySQL 5.5.3 Anda harus menggunakan utf8mb4 daripada utf8. Keduanya merujuk pada pengkodean UTF-8, tetapi yang lebih tua utf8 memiliki pembatasan khusus MySQL untuk mencegah penggunaan karakter bernomor di atas 0xFFFD.

  • Ketepatan

    utf8mb4_unicode_ci didasarkan pada standar Unicode untuk menyortir dan membandingkan, yang disusun secara akurat dalam berbagai bahasa yang sangat luas.

    utf8mb4_general_ci gagal untuk menerapkan semua aturan penyortiran Unicode, yang akan menghasilkan penyortiran yang tidak diinginkan dalam beberapa situasi, seperti ketika menggunakan bahasa atau karakter tertentu.

  • Kinerja

    utf8mb4_general_ci lebih cepat dalam perbandingan dan penyortiran, karena dibutuhkan banyak pintasan yang terkait dengan kinerja.

    Pada server modern, peningkatan kinerja ini akan dapat diabaikan. Itu dibuat dalam waktu ketika server memiliki sebagian kecil dari kinerja CPU komputer saat ini.

    utf8mb4_unicode_ci, yang menggunakan aturan Unicode untuk menyortir dan membandingkan, menggunakan algoritma yang cukup rumit untuk penyortiran yang benar dalam berbagai bahasa dan saat menggunakan berbagai karakter khusus. Aturan-aturan ini perlu mempertimbangkan konvensi spesifik bahasa; tidak semua orang mengurutkan karakter mereka dalam apa yang kita sebut 'urutan abjad'.

Sejauh bahasa Latin (yaitu "Eropa") pergi, tidak ada banyak perbedaan antara pemilahan Unicode dan yang disederhanakan utf8mb4_general_ci menyortir di MySQL, tetapi masih ada beberapa perbedaan:

  • Sebagai contoh, koleksi Unicode menyortir "ß" seperti "ss", dan "Œ" seperti "OE" karena orang yang menggunakan karakter tersebut biasanya ingin, sedangkan utf8mb4_general_ci mengurutkan mereka sebagai karakter tunggal (mungkin seperti "s" dan "e" masing-masing).

  • Beberapa karakter Unicode didefinisikan sebagai ignorable, yang berarti mereka tidak seharusnya menghitung urutan sortir dan perbandingan harus berpindah ke karakter berikutnya. utf8mb4_unicode_ci menangani ini dengan benar.

Dalam bahasa non-latin, seperti bahasa atau bahasa Asia dengan abjad yang berbeda, mungkin ada banyak lebih perbedaan antara pengurutan Unicode dan yang disederhanakan utf8mb4_general_ci penyortiran. Kesesuaian utf8mb4_general_ci akan sangat bergantung pada bahasa yang digunakan. Untuk beberapa bahasa, itu akan sangat tidak memadai.

Apa yang sebaiknya Anda gunakan?

Hampir tidak ada alasan untuk menggunakannya utf8mb4_general_ci lagi, karena kami telah meninggalkan titik di mana kecepatan CPU cukup rendah sehingga perbedaan kinerja akan menjadi penting. Database Anda hampir pasti akan dibatasi oleh kemacetan lain dari ini.

Perbedaan dalam kinerja hanya akan dapat diukur dalam situasi yang sangat khusus, dan jika itu Anda, Anda mungkin sudah mengetahuinya. Jika Anda mengalami pemilahan yang lambat, dalam hampir semua kasus, ini akan menjadi masalah dengan indeks / rencana kueri Anda. Mengubah fungsi pengumpulan Anda seharusnya tidak tinggi pada daftar hal-hal untuk memecahkan masalah.

Di masa lalu, beberapa orang merekomendasikan untuk menggunakannya utf8mb4_general_ci kecuali bila pengurutan akurat akan cukup penting untuk membenarkan biaya kinerja. Hari ini, biaya kinerja itu telah menghilang, dan pengembang memperlakukan internasionalisasi lebih serius.

Satu hal lain yang akan saya tambahkan adalah bahwa bahkan jika Anda tahu aplikasi Anda hanya mendukung bahasa Inggris, mungkin masih perlu berurusan dengan nama orang-orang, yang seringkali dapat berisi karakter yang digunakan dalam bahasa lain yang sama pentingnya untuk mengurutkan dengan benar . Menggunakan aturan Unicode untuk semuanya membantu menambah ketenangan pikiran bahwa orang Unicode yang sangat pintar telah bekerja sangat keras untuk membuat pengurutan bekerja dengan benar.


1267
2018-04-20 05:19



Saya ingin tahu apa perbedaan kinerja antara menggunakan utf8_general_ci dan utf8_unicode_ci, tetapi saya tidak menemukan benchmark apa pun yang tercantum di Internet, jadi saya memutuskan untuk membuat tolok ukur sendiri.

Saya membuat 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;

Lalu saya mengisinya dengan data acak dengan menjalankan prosedur tersimpan ini:

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 membuat prosedur yang tersimpan berikut untuk melakukan benchmark SELECT sederhana, SELECT dengan LIKE, dan sorting (PILIH dengan ORDER BY):

CREATE 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 tersimpan di atas utf8_general_ci collation digunakan, tetapi tentu saja selama tes saya menggunakan utf8_general_ci dan utf8_unicode_ci.

Saya memanggil setiap prosedur yang tersimpan 5 kali untuk setiap pemeriksaan (5 kali untuk utf8_general_ci dan 5 kali untuk utf8_unicode_ci) dan kemudian menghitung nilai rata-rata.

Hasil saya adalah:

benchmark_simple_select () dengan utf8_general_ci: 9957 ms
benchmark_simple_select () dengan utf8_unicode_ci: 10271 ms
Dalam benchmark ini menggunakan utf8_unicode_ci lebih lambat dari utf8_general_ci sebesar 3,2%.

benchmark_select_like () dengan utf8_general_ci: 11441 ms
benchmark_select_like () dengan utf8_unicode_ci: 12811 ms
Dalam benchmark ini menggunakan utf8_unicode_ci lebih lambat dari utf8_general_ci sebesar 12%.

benchmark_order_by () dengan utf8_general_ci: 11944 ms
benchmark_order_by () dengan utf8_unicode_ci: 12887 ms
Dalam benchmark ini menggunakan utf8_unicode_ci lebih lambat dari utf8_general_ci sebesar 7,9%.


127
2018-03-02 02:53



Posting ini menggambarkannya dengan sangat baik.

Singkatnya: utf8_unicode_ci menggunakan Algoritma Unicode Collation seperti yang didefinisikan dalam standar Unicode, sedangkan utf8_general_ci adalah jenis urutan yang lebih sederhana yang menghasilkan hasil sorting "kurang akurat".


33
2018-01-01 00:31



Lihat manual mysql, Set Karakter Unicode bagian:

Untuk setiap set karakter Unicode,   operasi dilakukan menggunakan   Kolasi _general_ci lebih cepat dari pada pengumpulan _unicode_ci.   Sebagai contoh, perbandingan untuk   kolasi utf8_general_ci lebih cepat,   tetapi sedikit kurang benar, daripada   perbandingan untuk utf8_unicode_ci. Itu   alasan untuk ini adalah itu   utf8_unicode_ci mendukung pemetaan seperti itu   sebagai ekspansi; yaitu, ketika satu   karakter membandingkan sama dengan   kombinasi karakter lain. Untuk   Misalnya, dalam bahasa Jerman dan beberapa lainnya   bahasa "ß" sama dengan "ss".   utf8_unicode_ci juga mendukung   kontraksi dan karakter yang tidak jelas.   utf8_general_ci adalah koleksi warisan   yang tidak mendukung ekspansi,   kontraksi, atau karakter yang dapat diabaikan.   Itu bisa hanya satu-ke-satu   perbandingan antar karakter.

Jadi untuk meringkas, utf_general_ci menggunakan kumpulan perbandingan yang lebih kecil dan kurang benar (menurut standar) daripada utf_unicode_ci yang harus terapkan seluruh standar. Set general_ci akan lebih cepat karena ada lebih sedikit perhitungan yang harus dilakukan.


4
2018-04-20 04:09



Singkat kata:

Jika Anda membutuhkan urutan penyortiran yang lebih baik - gunakan utf8_unicode_ci (ini adalah metode yang disukai),

tetapi jika Anda benar-benar tertarik pada kinerja - gunakan utf8_general_ci, tetapi ketahuilah bahwa itu sedikit ketinggalan jaman.

Perbedaan dalam hal kinerja sangat sedikit.


3
2018-03-06 11:51