656 Stimmen

MySQL-Fehler #1071 - Der angegebene Schlüssel war zu lang; die maximale Schlüssellänge beträgt 767 Bytes

Wenn ich den folgenden Befehl ausführe:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

Ich habe diese Fehlermeldung erhalten:

#1071 - Specified key was too long; max key length is 767 bytes

Informationen über Spalte1 und Spalte2:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

でしょう varchar(20) benötigt nur 21 Bytes, während varchar(500) benötigt nur 501 Bytes. Die Gesamtzahl der Bytes beträgt also 522, also weniger als 767. Warum habe ich dann die Fehlermeldung erhalten?

#1071 - Specified key was too long; max key length is 767 bytes

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

605voto

OMG Ponies Punkte 312816

767 Bytes in MySQL Version 5.6 (und frühere Versionen), ist die angegebene Präfixbegrenzung für InnoDB-Tabellen. Für MyISAM-Tabellen ist sie 1.000 Byte lang. Diese Grenze wurde erhöht auf 3072 Bytes In MySQL Version 5.7 (und aufwärts).

Sie müssen sich auch bewusst sein, dass, wenn Sie einen Index auf ein großes Zeichen oder varchar Feld, das utf8mb4 kodiert ist, müssen Sie die maximale Länge des Indexpräfixes von 767 Byte (oder 3072 Byte) durch 4 teilen, was zu 191 . Dies liegt daran, dass die maximale Länge einer utf8mb4 Zeichen sind vier Bytes. Für ein utf8 Zeichen wären es drei Bytes, was eine maximale Länge des Indexpräfixes von 255 (oder minus Null-Terminator, 254 Zeichen).

Eine Möglichkeit, die Sie haben, ist, einfach eine Untergrenze für Ihre VARCHAR Felder.

Eine weitere Möglichkeit (nach der Antwort auf diese Frage ) ist es, die Teilmenge der Spalte und nicht den gesamten Betrag zu erhalten, d.h.:

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

Ändern Sie die Einstellungen so, wie Sie es brauchen, um den Schlüssel anzuwenden, aber ich frage mich, ob es sich lohnen würde, Ihr Datenmodell in Bezug auf diese Entität zu überprüfen, um zu sehen, ob es Verbesserungen gibt, die es Ihnen ermöglichen würden, die beabsichtigten Geschäftsregeln zu implementieren, ohne auf die MySQL-Beschränkung zu stoßen.

5 Stimmen

Anwendung durch Angabe einer Teilmenge der Spalte anstelle des gesamten Betrags. Eine gute Lösung.

0 Stimmen

@OMGPonies: Weißt du zufällig, ob DB2/MSSQL/Oracle die gleiche Beschränkung der Indexgröße haben? Zum Beispiel HSQL hat keine solche Beschränkung...

0 Stimmen

@dma_k: Ich habe keine Erfahrung mit DB2, aber ich habe das Problem bei SQL Server oder Oracle nicht erlebt.

446voto

Aley Punkte 8230

Wenn Sie das Limit erreicht haben. Stellen Sie Folgendes ein.

  • INNODB utf8 VARCHAR(255)
  • INNODB utf8mb4 VARCHAR(191)

43 Stimmen

Dies ist die beste Antwort. Einfach, direkt auf den Punkt gebracht und beinhaltet auch utf8mb4 Grenze (die bei neueren Datenbanken am häufigsten verwendete Kodierung, da sie Emojis usw. akzeptiert).

15 Stimmen

Denn 767 / 4 ~= 191 , und 767 / 3 ~= 255

15 Stimmen

Wo und wie ist sie einzustellen?

427voto

PinkTurtle Punkte 6830

Wenn jemand Probleme mit INNODB / Utf-8 hat und versucht, eine UNIQUE Index auf eine VARCHAR(256) Feld, schalten Sie es auf VARCHAR(255) . Es scheint, dass 255 die Einschränkung ist.

260 Stimmen

Die Anzahl der zulässigen Zeichen hängt nur von Ihrem Zeichensatz ab. UTF8 kann bis zu 3 Byte pro Zeichen verwenden, utf8mb4 bis zu 4 Byte und latin1 nur 1 Byte. Bei utf8 ist Ihre Schlüssellänge also auf 255 Zeichen begrenzt, da 3*255 = 765 < 767 .

10 Stimmen

Das hat mir eine Menge Frustration erspart - vielen Dank. Es sollte die akzeptierte Antwort IMO sein, wenn man bedenkt, dass der Benutzer InnoDB verwendet, indem er behauptet, dass sie eine 767b-Beschränkung treffen.

8 Stimmen

Wie Stefan Endrullis sagte, hängt es vom Zeichensatz ab. Wenn Sie UTF8 verwenden, das 3 Bytes verwendet: 255x3=765, was unter der Grenze von 767 liegt, während 256x3=768, was höher ist. Aber wenn Sie UTF8mb4 verwenden, ist 255*4=1020, also keine wirkliche Lösung.

148voto

morganwahl Punkte 1648

MySQL nimmt den ungünstigsten Fall für die Anzahl der Bytes pro Zeichen in der Zeichenkette an. Für die MySQL-'utf8'-Kodierung sind das 3 Bytes pro Zeichen, da diese Kodierung keine Zeichen über U+FFFF . Bei der MySQL-Kodierung "utf8mb4" sind es 4 Byte pro Zeichen, da MySQL dies als UTF-8 bezeichnet.

Unter der Annahme, dass Sie "utf8" verwenden, nimmt Ihre erste Spalte 60 Bytes des Indexes ein und Ihre zweite weitere 1500 Bytes.

5 Stimmen

- Das bedeutet vermutlich, dass ich sie bei Verwendung von utf8mb4 auf (höchstens) 191 setzen muss, da 191*4 = 764 < 767.

2 Stimmen

@Isaac Ja, genau,

2 Stimmen

Ich denke, das könnte die richtige Antwort sein, aber könnten Sie näher erläutern, was man tun müsste, um ein solches Problem zu beheben? Zumindest für MySQL-Neulinge wie mich?

59voto

Ali Shaukat Punkte 885

Lösung für Laravel Framework

Gemäß Laravel 5.4.* Dokumentation Sie müssen die Standard-Zeichenfolgenlänge in der Datei boot Methode der app/Providers/AppServiceProvider.php Datei wie folgt:

use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

Erläuterung dieser Festsetzung, gegeben durch Laravel 5.4.* Dokumentation :

Laravel verwendet die utf8mb4 Zeichensatz, der auch die Speicherung von "Emojis" in der Datenbank unterstützt. Wenn Sie eine ältere MySQL-Version als 5.7.7 oder eine ältere MariaDB-Version als 10.2.2 verwenden, müssen Sie möglicherweise die Standardlänge der von Migrationen erzeugten Zeichenketten manuell konfigurieren, damit MySQL Indizes für sie erstellen kann. Sie können dies konfigurieren, indem Sie die Schema::defaultStringLength Methode innerhalb Ihrer AppServiceProvider .

Alternativ können Sie auch die Option innodb_large_prefix Option für Ihr Datenbank. In der Dokumentation Ihrer Datenbank finden Sie Anweisungen dazu wie Sie diese Option richtig aktivieren.

11 Stimmen

@BojanPetkovic gut ich kam gerade von einem Laravel Problem, und diese Antwort tatsächlich mein Problem gelöst.

0 Stimmen

Diese Antwort ist großartig. Aber weiß jemand, warum genau das funktioniert?

1 Stimmen

@Bobby Laravel Dokumentation gibt seine Erklärung in der Überschrift "Index Lengths & MySQL / MariaDB" laravel.com/docs/5.4/migrations#erstellen-indexe

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X