Wir stießen auf dieses Problem, als wir versuchten, einen UNIQUE-Index zu einem VARCHAR(255)-Feld mit utf8mb4 hinzuzufügen. Obwohl das Problem hier bereits gut beschrieben ist, wollte ich einige praktische Ratschläge hinzufügen, wie wir das Problem herausgefunden und gelöst haben.
Bei der Verwendung von utf8mb4 zählen die Zeichen als 4 Byte, während sie unter utf8 als 3 Byte gezählt werden können. InnoDB-Datenbanken können Indizes nur 767 Bytes enthalten. Bei Verwendung von utf8 können Sie also 255 Zeichen speichern (767/3 = 255), bei Verwendung von utf8mb4 jedoch nur 191 Zeichen (767/4 = 191).
Sie sind durchaus in der Lage, reguläre Indizes für VARCHAR(255)
Felder mit utf8mb4, aber die Indexgröße wird automatisch bei 191 Zeichen abgeschnitten - wie unique_key
hier:
Das ist in Ordnung, denn reguläre Indizes dienen nur dazu, dass MySQL Ihre Daten schneller durchsuchen kann. Das gesamte Feld muss nicht indiziert werden.
Warum schneidet MySQL den Index bei regulären Indizes automatisch ab, gibt aber einen expliziten Fehler aus, wenn dies bei eindeutigen Indizes versucht wird? Damit MySQL in der Lage ist, herauszufinden, ob der eingefügte oder aktualisierte Wert bereits existiert, muss er tatsächlich den gesamten Wert indizieren und nicht nur einen Teil davon.
Wenn Sie einen eindeutigen Index für ein Feld haben wollen, muss der gesamte Inhalt des Feldes in den Index passen. Für utf8mb4 bedeutet dies, dass Sie die Länge Ihrer VARCHAR-Felder auf 191 Zeichen oder weniger reduzieren müssen. Wenn Sie utf8mb4 für diese Tabelle oder dieses Feld nicht benötigen, können Sie es auf utf8 zurücksetzen und Ihre 255 langen Felder beibehalten.
5 Stimmen
Da es sich nicht um 520 Bytes, sondern um 2080 Bytes handelt, die weit über 767 Bytes hinausgehen, könnten Sie Spalte1 varchar(20) und Spalte2 varchar(170) verwenden. Wenn Sie eine Zeichen/Byte-Entsprechung wünschen, verwenden Sie latin1
3 Stimmen
Ich denke, Ihre Berechnung ist ein bisschen falsch hier. mysql verwendet 1 oder 2 zusätzliche Bytes, um die Werte Länge aufzeichnen: 1 Byte, wenn die maximale Länge der Spalte 255 Bytes oder weniger ist, 2, wenn es länger als 255 Bytes ist. die utf8_general_ci Codierung benötigt 3 Bytes pro Zeichen so varchar (20) verwendet 61 Bytes, varchar (500) verwendet 1502 Bytes insgesamt 1563 Bytes
3 Stimmen
Mysql> select maxlen, character_set_name from information_schema.character_sets where character_set_name in('latin1', 'utf8', 'utf8mb4'); maxlen | character_set_name ------ | ------------------- 1 | latin1 ------ | ------------------- 3 | utf8 ------ | ------------------- 4 | utf8mb4
24 Stimmen
'wenn Sie eine Zeichen/Byte-Äquivalenz wünschen, verwenden Sie latin1' Bitte Tun Sie das nicht . Latin1 ist wirklich, wirklich scheiße. Du wirst es bereuen.
0 Stimmen
Siehe stackoverflow.com/a/52778785/2137210 für die Lösung