Suntingan September 2021:Saya telah menggunakan MySQL 8.0 selama beberapa tahun sekarang, jadi inilah beberapa info terbaru.
Manual MySQL sekarang memiliki halaman yang sangat informatif mengenai konversi antara utf8mb3
(saat ini juga dikenal sebagai utf8
) dan utf8mb4
. utf8mb3
tidak digunakan lagi dan akan dihapus
pada akhirnya; dan ketika dihapus, aliasnya saat ini, utf8
, akan merujuk ke utf8mb4
sebagai gantinya.
Dengan utf8mb3
yang tidak digunakan lagi , Anda dapat menyimpan hingga 255 karakter dalam indeks, sedangkan dengan utf8mb4
, hingga 191, saat menggunakan COMPACT
atau REDUNDANT
format baris.
Dengan COMPRESSED
atau DYNAMIC
format baris, prefiks kunci indeks dapat mencapai 3072 byte. Dengan mereka, Anda dapat mengindeks hingga 1024 karakter untuk utf8mb3
, dan 768 karakter untuk utf8mb4
.
Di bawah ini adalah jawaban saya sebelumnya, yang menjelaskan beberapa logika di balik jumlah karakter Anda dapat mengindeks versus jumlah byte .
Saya harus merevisi jawaban saya karena penelitian saya. Saya awalnya memposting ini (mengutip diri saya sendiri):
Saya yakin jawabannya adalah Anda tidak dapat mengetahui berapa banyak karakter yang akan ada dalam indeks karena Anda tidak dapat mengetahui berapa byte karakter Anda (kecuali jika Anda melakukan sesuatu untuk mengecualikan karakter multi-byte).
Dan saya tidak yakin, tetapi mungkin masih benar, tetapi tidak seperti yang saya pikirkan.
Ini jawaban yang benar:
MySQL mengasumsikan 3 byte per karakter utf8. 255 karakter adalah ukuran indeks maksimum yang dapat Anda tentukan per kolom, karena 256x3=768, yang melanggar batas 767 byte.
Jika Anda tidak menentukan ukuran indeks, MySQL memilih ukuran maksimum (yaitu 255 per kolom). Batasan UNIK tidak dapat diletakkan pada kolom utf8 yang panjangnya lebih besar dari 255, karena indeks unik harus berisi seluruh nilai sel. Tetapi indeks biasa dapat digunakan - itu hanya akan mengindeks 255 karakter pertama (atau 767 byte pertama?). Dan di situlah masih ada misteri bagi saya.
Misteri:Saya dapat melihat mengapa MySQL mengasumsikan 3 byte per karakter, untuk keamanan, karena jika tidak, batasan UNIK dapat dipatahkan. Tetapi dokumen tampaknya menyarankan bahwa indeks sebenarnya berukuran dalam byte, bukan karakter. Jadi, misalkan Anda memberi 255 char (765 byte) indeks pada varchar(256 ) kolom. Jika karakter yang Anda simpan semuanya adalah ASCII, karakter 1-byte, seperti A-Z, a-z, 0-9, maka Anda dapat memasukkan seluruh kolom ke dalam indeks 767 byte. Dan sepertinya itulah yang akan benar-benar terjadi.
Di bawah ini adalah beberapa informasi lebih lanjut dari jawaban asli saya tentang karakter, byte, dll.
Menurut wikipedia , panjang karakter UTF-8 bisa 1,2, 3, atau 4 byte. Tapi, menurut dokumentasi mysql ini , ukuran karakter maksimal adalah 3 byte, sehingga indeks indeks kolom apa pun yang melebihi 255 karakter mungkin mencapai batas byte tersebut. Tapi seperti yang saya pahami, mungkin tidak. Jika sebagian besar karakter Anda berada dalam rentang ASCII, maka ukuran karakter rata-rata Anda akan mendekati 1 byte. Jika ukuran karakter rata-rata Anda, misalnya, 1,3 byte (kebanyakan 1 byte, tetapi sejumlah besar karakter 2-3 byte), maka Anda dapat menentukan indeks 767/1.3
Jadi, jika Anda menyimpan sebagian besar karakter 1-byte, batas karakter Anda yang sebenarnya akan lebih seperti:767 / 1.3 =590. Tapi ternyata bukan itu cara kerjanya. 255 karakter adalah batasnya.
Seperti yang disebutkan dalam dokumentasi MySQL ini ,
Batas awalan diukur dalam byte, sedangkan panjang awalan dalam pernyataan CREATE INDEX ditafsirkan sebagai jumlah karakter untuk tipe data nonbiner (CHAR, VARCHAR, TEXT). Pertimbangkan hal ini saat menentukan panjang awalan untuk kolom yang menggunakan kumpulan karakter multi-byte.
Tampaknya MySQL menyarankan orang untuk melakukan perhitungan/perkiraan seperti yang baru saja saya lakukan untuk menentukan ukuran kunci Anda untuk kolom varchar. Tapi nyatanya kamu tidak bisa tentukan indeks yang lebih besar dari 255 untuk kolom utf8.
Terakhir, jika Anda merujuk kembali ke tautan kedua saya lagi, ada juga ini:
Saat opsi konfigurasi innodb_large_prefix diaktifkan, batas panjang ini dinaikkan menjadi 3072 byte, untuk tabel InnoDB yang menggunakan format baris DYNAMIC dan COMPRESSED.
Jadi sepertinya Anda bisa mendapatkan indeks yang jauh lebih besar jika Anda mau, dengan sedikit penyesuaian. Pastikan format baris DINAMIS atau TERKOMPRESI. Anda mungkin dapat menentukan indeks 1023 atau 1024 karakter dalam kasus itu.
Omong-omong, ternyata Anda dapat menyimpan karakter 4-byte menggunakan [kumpulan karakter utf8mb4][4]. Kumpulan karakter utf8 tampaknya hanya menyimpan karakter ["pesawat 0"][5].EDIT:
Saya baru saja mencoba membuat indeks komposit pada kolom varchar(511) dengan kolom tinyint(1) dan mendapat pesan kesalahan yang mengatakan ukuran indeks maks adalah 767 byte. Ini membuat saya percaya bahwa MySQL mengasumsikan kolom set karakter utf8 akan berisi 3 byte per karakter (maksimum), dan memungkinkan Anda untuk menggunakan maksimal 255 karakter. Tapi mungkin itu hanya dengan indeks komposit. Saya akan memperbarui jawaban saya saat saya mengetahui lebih lanjut. Tapi untuk saat ini saya biarkan ini sebagai editan.