Saya punya tabel dengan kunci utama yaitu varchar (255). Beberapa kasus muncul di mana 255 karakter tidak cukup. Saya mencoba mengubah bidang menjadi teks, tetapi saya mendapatkan kesalahan berikut:
BLOB/TEXT column 'message_id' used in key specification without a key length
bagaimana saya bisa memperbaikinya?
sunting: Saya juga harus menunjukkan tabel ini memiliki kunci primer komposit dengan beberapa kolom.
mysql
sql
mysql-error-1170
GSto
sumber
sumber
UNIQUE
kunci?Jawaban:
Kesalahan terjadi karena MySQL hanya dapat mengindeks karakter N pertama dari BLOB atau
TEXT
kolom. Jadi Kesalahan terutama terjadi ketika ada jenis bidang / kolomTEXT
atau blob atau mereka milikTEXT
atauBLOB
jenis sepertiTINYBLOB
,MEDIUMBLOB
,LONGBLOB
,TINYTEXT
,MEDIUMTEXT
, danLONGTEXT
bahwa Anda mencoba untuk membuat kunci primer atau indeks. Dengan nilai penuhBLOB
atauTEXT
tanpa panjang, MySQL tidak dapat menjamin keunikan kolom karena ukurannya variabel dan dinamis. Jadi, ketika menggunakanBLOB
atauTEXT
mengetik sebagai indeks, nilai N harus disediakan sehingga MySQL dapat menentukan panjang kunci. Namun, MySQL tidak mendukung batas panjang kunci padaTEXT
atauBLOB
.TEXT(88)
tidak akan bekerja.Kesalahan juga akan muncul ketika Anda mencoba untuk mengkonversi kolom tabel dari
non-TEXT
dannon-BLOB
ketik sepertiVARCHAR
danENUM
keTEXT
atauBLOB
ketik, dengan kolom yang sudah didefinisikan sebagai batasan atau indeks unik. Perintah Alter Table SQL akan gagal.Solusi untuk masalah ini adalah menghapus kolom
TEXT
atauBLOB
dari indeks atau batasan unik atau mengatur bidang lain sebagai kunci utama. Jika Anda tidak dapat melakukan itu, dan ingin menempatkan batas pada kolomTEXT
atauBLOB
, coba gunakanVARCHAR
jenis dan tempatkan batas panjang di atasnya. Secara default,VARCHAR
dibatasi hingga maksimum 255 karakter dan batasnya harus ditentukan secara implisit dalam braket setelah deklarasi, yaituVARCHAR(200)
akan membatasi hanya untuk 200 karakter saja.Kadang-kadang, meskipun Anda tidak menggunakan
TEXT
atauBLOB
jenis terkait di tabel Anda, Kesalahan 1170 juga dapat muncul. Ini terjadi dalam situasi seperti ketika Anda menentukanVARCHAR
kolom sebagai kunci utama, tetapi salah mengatur panjang atau ukuran karakter.VARCHAR
hanya dapat menerima hingga 256 karakter, sehingga hal seperti ituVARCHAR(512)
akan memaksa MySQL untuk secara otomatis mengkonversiVARCHAR(512)
keSMALLTEXT
tipe data, yang kemudian gagal dengan kesalahan 1170 pada panjang kunci jika kolom digunakan sebagai kunci utama atau indeks unik atau non-unik. Untuk mengatasi masalah ini, tentukan angka kurang dari 256 sebagai ukuran untukVARCHAR
bidang.Referensi: Kesalahan MySQL 1170 (42000): Kolom BLOB / TEXT Digunakan dalam Spesifikasi Kunci Tanpa Panjang Kunci
sumber
Anda harus menentukan bagian mana dari
TEXT
kolom yang ingin Anda indeks.InnoDB
memiliki batasan768
byte per kunci indeks dan Anda tidak akan dapat membuat indeks lebih lama dari itu.Ini akan bekerja dengan baik:
Perhatikan bahwa nilai maksimum ukuran kunci tergantung pada charset kolom. Ini
767
karakter untuk charset byte tunggal sepertiLATIN1
dan hanya255
karakter untukUTF8
(MySQL
hanya menggunakanBMP
yang membutuhkan paling banyak3
byte per karakter)Jika Anda membutuhkan seluruh kolom Anda menjadi
PRIMARY KEY
, hitungSHA1
atauMD5
hash dan gunakan sebagaiPRIMARY KEY
.sumber
REDUNDANT
atauCOMPACT
baris. Misalnya, Anda mungkin mencapai batas ini dengan indeks awalan kolom lebih dari 255 karakter padaTEXT
atauVARCHAR
kolom, dengan asumsi set karakter utf8mb3 dan maksimum 3 byte untuk setiap karakter.REDUNDANT
danCOMPACT
apakah hanya format yang tersedia pada saat jawaban ini diberikan.Anda bisa menentukan panjang kunci dalam permintaan tabel alter, seperti:
sumber
MySQL melarang pengindeksan nilai penuh
BLOB
,TEXT
danVARCHAR
kolom panjang karena data yang dikandungnya bisa sangat besar, dan secara implisit indeks DB akan besar, artinya tidak ada manfaat dari indeks.MySQL mengharuskan Anda menentukan karakter N pertama yang akan diindeks, dan triknya adalah memilih nomor N yang cukup panjang untuk memberikan selektivitas yang baik, tetapi cukup pendek untuk menghemat ruang. Awalan harus cukup panjang untuk membuat indeks hampir berguna jika Anda akan mengindeks seluruh kolom.
Sebelum kita melangkah lebih jauh, mari kita mendefinisikan beberapa istilah penting. Selektivitas indeks adalah rasio total nilai indeks yang berbeda dan jumlah baris . Berikut adalah satu contoh untuk tabel tes:
Jika kita hanya mengindeks karakter pertama (N = 1), maka tabel indeks akan terlihat seperti tabel berikut:
Dalam hal ini, selektivitas indeks sama dengan IS = 1/3 = 0,33.
Mari kita lihat apa yang akan terjadi jika kita menambah jumlah karakter yang diindeks menjadi dua (N = 2).
Dalam skenario ini IS = 2/3 = 0,66 yang berarti kami meningkatkan selektivitas indeks, tetapi kami juga meningkatkan ukuran indeks. Triknya adalah mencari angka minimal N yang akan menghasilkan secara maksimal selektivitas indeks .
Ada dua pendekatan yang dapat Anda lakukan perhitungan untuk tabel database Anda. Saya akan membuat demonstrasi di Internet dump database ini .
Katakanlah kita ingin menambahkan kolom last_name di tabel karyawan ke indeks, dan kami ingin mendefinisikan angka terkecil N yang akan menghasilkan selektivitas indeks terbaik.
Pertama mari kita kenali nama terakhir yang paling sering:
Seperti yang Anda lihat, nama belakang Baba adalah yang paling sering. Sekarang kita akan menemukan awalan last_name paling sering terjadi , dimulai dengan awalan lima huruf.
Ada lebih banyak kejadian setiap awalan, yang berarti kita harus meningkatkan angka N hingga nilainya hampir sama seperti pada contoh sebelumnya.
Ini adalah hasil untuk N = 9
Ini adalah hasil untuk N = 10.
Ini hasil yang sangat bagus. Ini berarti bahwa kita dapat membuat indeks pada kolom
last_name
dengan mengindeks hanya 10 karakter pertama. Di kolom definisi tabellast_name
didefinisikan sebagaiVARCHAR(16)
, dan ini berarti kita telah menyimpan 6 byte (atau lebih jika ada karakter UTF8 dalam nama belakang) per entri. Dalam tabel ini ada 1637 nilai berbeda dikalikan dengan 6 byte sekitar 9KB, dan bayangkan bagaimana angka ini akan tumbuh jika tabel kita berisi jutaan baris.Anda dapat membaca cara-cara lain untuk menghitung jumlah N dalam indeks Prefixed posting saya di MySQL .
sumber
Saya mendapatkan kesalahan ini saat menambahkan indeks ke tabel dengan kolom jenis teks. Anda perlu mendeklarasikan jumlah ukuran yang ingin Anda gunakan untuk setiap jenis teks.
Masukkan jumlah ukuran dalam kurung ()
Jika terlalu banyak byte digunakan, Anda dapat mendeklarasikan ukuran dalam tanda kurung untuk varchar untuk mengurangi jumlah yang digunakan untuk pengindeksan. Ini bahkan jika Anda menyatakan ukuran untuk tipe yang sudah seperti varchar (1000). Anda tidak perlu membuat tabel baru seperti yang dikatakan orang lain.
Menambahkan indeks
Menambahkan indeks unik
sumber
CATATAN : 767 adalah jumlah karakter yang dibatasi hingga mana MySQL akan mengindeks kolom saat berurusan dengan indeks gumpalan / teks
Ref: http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
sumber
Cara hebat lainnya untuk menangani hal ini adalah membuat bidang TEXT Anda tanpa kendala unik dan menambahkan bidang VARCHAR saudara yang unik dan berisi intisari (MD5, SHA1, dll.) Dari bidang TEXT. Hitung dan simpan intisari seluruh bidang TEXT saat Anda menyisipkan atau memperbarui bidang TEXT maka Anda memiliki kendala keunikan atas seluruh bidang TEXT (bukan bagian utama) yang dapat dicari dengan cepat.
sumber
Tidak memiliki nilai lama sebagai kunci utama. Itu akan menghancurkan kinerja Anda. Lihat manual mysql, bagian 13.6.13 'Penyesuaian dan Pemecahan Masalah InnoDB'.
Alih-alih, minta pengganti int key sebagai primary (dengan auto_increment), dan loong key Anda sebagai UNIQUE sekunder.
sumber
Tambahkan kolom varChar (255) lain (dengan default sebagai string kosong bukan nol) untuk menahan overflow ketika 255 karakter tidak cukup, dan ubah PK ini untuk menggunakan kedua kolom. Ini kedengarannya tidak seperti skema database yang dirancang dengan baik, dan saya akan merekomendasikan mendapatkan pemodel data untuk melihat apa yang Anda miliki dengan pandangan ke arah refactoring untuk Normalisasi lebih lanjut.
sumber
Solusi untuk masalah ini adalah bahwa dalam
CREATE TABLE
pernyataan Anda, Anda dapat menambahkan kendalaUNIQUE ( problemtextfield(300) )
setelah kolom membuat definisi untuk menentukankey
panjang300
karakter untukTEXT
bidang, misalnya. Maka300
karakter pertamaproblemtextfield
TEXT
bidang harus unik, dan perbedaan setelah itu akan diabaikan.sumber
Juga, jika Anda ingin menggunakan indeks dalam bidang ini, Anda harus menggunakan mesin penyimpanan MyISAM dan tipe indeks FULLTEXT.
sumber
Sejauh ini tidak ada yang menyebutkan ... dengan utf8mb4 yang merupakan 4-byte dan juga dapat menyimpan emotikon (kita seharusnya tidak pernah lagi menggunakan utf8 3-byte) dan kita dapat menghindari kesalahan seperti
Incorrect string value: \xF0\x9F\x98\...
kita seharusnya tidak menggunakan VARCHAR (255) melainkan VARCHAR ( lebih tepatnya) 191) karena dalam kasus utf8mb4 dan VARCHAR (255) bagian data yang sama disimpan di luar halaman dan Anda tidak dapat membuat indeks untuk kolom VARCHAR (255) tetapi untuk VARCHAR (191) Anda bisa. Itu karena ukuran kolom maksimum yang diindeks adalah 767 byte untuk ROW_FORMAT = COMPACT atau ROW_FORMAT = REDUNDANT.Untuk format baris yang lebih baru ROW_FORMAT = DYNAMIC atau ROW_FORMAT = COMPRESSED (yang membutuhkan format file yang lebih baru innodb_file_format = Barracuda bukan Antelope yang lebih tua) ukuran kolom yang diindeks maksimum adalah 3072. Ini tersedia karena MySQL> = 5.6.3 ketika innodb_large_prefix = 1 (dinonaktifkan secara default untuk MySQL <= 5.7.6 dan diaktifkan secara default untuk MySQL> = 5.7.7). Jadi dalam hal ini kita dapat menggunakan VARCHAR (768) untuk utf8mb4 (atau VARCHAR (1024) untuk utf8 lama) untuk kolom yang diindeks. Opsi innodb_large_prefix sudah tidak digunakan lagi sejak 5.7.7 karena perilakunya built-in MySQL 8 (dalam versi ini opsi dihapus).
sumber
Anda harus mengubah jenis kolom ke
varchar
atauinteger
untuk pengindeksan.sumber
Buka mysql
edit table
-> ubah jenis kolom menjadivarchar(45)
.sumber
Gunakan seperti ini
sumber