it-swarm.com.de

# 1071 - Angegebener Schlüssel war zu lang; Die maximale Schlüssellänge beträgt 1000 Byte

Ich weiß, dass Fragen mit diesem Titel bereits beantwortet wurden, aber bitte lesen Sie weiter. Ich habe alle anderen Fragen/Antworten zu diesem Fehler vor dem Posten gründlich gelesen.

Ich erhalte den obigen Fehler für die folgende Abfrage:

CREATE TABLE IF NOT EXISTS `pds_core_menu_items` (
  `menu_id` varchar(32) NOT NULL,
  `parent_menu_id` int(32) unsigned DEFAULT NULL,
  `menu_name` varchar(255) DEFAULT NULL,
  `menu_link` varchar(255) DEFAULT NULL,
  `plugin` varchar(255) DEFAULT NULL,
  `menu_type` int(1) DEFAULT NULL,
  `extend` varchar(255) DEFAULT NULL,
  `new_window` int(1) DEFAULT NULL,
  `rank` int(100) DEFAULT NULL,
  `hide` int(1) DEFAULT NULL,
  `template_id` int(32) unsigned DEFAULT NULL,
  `alias` varchar(255) DEFAULT NULL,
  `layout` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`menu_id`),
  KEY `index` (`parent_menu_id`,`menu_link`,`plugin`,`alias`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Hat jemand eine Idee warum und wie man es repariert? Der Haken ist: Dieselbe Abfrage funktioniert perfekt auf meinem lokalen Computer und auch auf meinem vorherigen Host. Übrigens handelt es sich um ein ausgereiftes Projekt - phpdevshell - also würde ich vermuten, dass diese Jungs wissen, was sie tun, obwohl Sie es nie wissen.

Jeder Hinweis wird geschätzt.

Ich benutze phpMyAdmin.

81
CodeVirtuoso

Wie @ Devart sagt, ist die Gesamtlänge Ihres Index zu lang.

Die kurze Antwort ist, dass Sie sowieso nicht so lange VARCHAR-Spalten indizieren sollten, da der Index sehr umfangreich und ineffizient sein wird.

Am besten verwenden Sie Präfix-Indizes, um nur einen linken Teil der Daten zu indizieren. Die meisten Ihrer Daten sind ohnehin viel kürzer als 255 Zeichen.

Sie können eine Präfixlänge pro Spalte angeben, wenn Sie den Index definieren. Beispielsweise:

...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...

Aber was ist die beste Präfixlänge für eine bestimmte Spalte? Hier ist eine Methode, um dies herauszufinden:

SELECT
 ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(`menu_link`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(`menu_link`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(`menu_link`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(`menu_link`),2) AS pct_length_100
FROM `pds_core_menu_items`;

In der Spalte menu_link Wird der Anteil der Zeilen angegeben, die nicht länger als eine bestimmte Zeichenfolge sind. Möglicherweise sieht die Ausgabe so aus:

+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
|         21.78 |         80.20 |        100.00 |         100.00 |
+---------------+---------------+---------------+----------------+

Dies zeigt Ihnen, dass 80% Ihrer Zeichenfolgen weniger als 20 Zeichen und alle Ihre Zeichenfolgen weniger als 50 Zeichen umfassen. Es ist also nicht erforderlich, mehr als eine Präfixlänge von 50 Zeichen zu indizieren, und es ist auf keinen Fall erforderlich, die gesamte Länge von 255 Zeichen zu indizieren.

PS: Die Datentypen INT(1) und INT(32) weisen auf ein weiteres Missverständnis in Bezug auf MySQL hin. Das numerische Argument hat keine Auswirkung auf die Speicherung oder den Wertebereich, der für die Spalte zulässig ist. INT ist immer 4 Byte groß und erlaubt immer Werte von -2147483648 bis 2147483647. Das numerische Argument dient zum Auffüllen von Werten während der Anzeige. Dies hat keine Auswirkung, es sei denn, Sie verwenden die Option ZEROFILL.

136
Bill Karwin

Dieser Fehler bedeutet, dass die Länge des Index index mehr als 1000 Byte beträgt. MySQL und Storage Engines können diese Einschränkung haben. Auf MySQL 5.5 ist ein ähnlicher Fehler aufgetreten. 'Angegebener Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 3072 Byte, wenn dieses Skript ausgeführt wird:

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UTF8 besteht aus mehreren Bytes, und die Schlüssellänge wird auf diese Weise berechnet - 500 * 3 * 6 = 9000 Bytes.

Beachten Sie jedoch, dass die nächste Abfrage funktioniert!

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

... weil ich CHARSET = latin1 verwendet habe, ist die Schlüssellänge in diesem Fall 500 * 6 = 3000 Bytes.

26
Devart

führen Sie diese Abfrage aus, bevor Sie eine Tabelle erstellen oder ändern.

SET @@global.innodb_large_prefix = 1;

dadurch wird die maximale Schlüssellänge auf 3072 Byte festgelegt

9
Raza Ahmed

Ich hatte dieses Problem und habe es folgendermaßen gelöst:

Ursache

Es gibt einen bekannten Fehler mit MySQL in Bezug auf MyISAM, den UTF8-Zeichensatz und die Indizes, die Sie hier überprüfen können.

Auflösung

  • Stellen Sie sicher, dass MySQL mit der InnoDB-Speicher-Engine konfiguriert ist.

  • Ändern Sie die standardmäßig verwendete Speicher-Engine so, dass neue Tabellen immer entsprechend erstellt werden:

    set GLOBAL storage_engine='InnoDb';

  • Verwenden Sie für MySQL 5.6 und höher Folgendes:

    SET GLOBAL default_storage_engine = 'InnoDB';

  • Und stellen Sie schließlich sicher, dass Sie die Anweisungen in Migration zu MySQL befolgen.

Referenz

6
Vishrant

Diese Indexgrößenbeschränkung scheint bei 64-Bit-Versionen von MySQL größer zu sein.

Ich bin auf diese Einschränkung gestoßen, als ich versucht habe, unsere Entwicklerdatenbank zu sichern und sie auf eine lokale VMWare-Virtuelle zu laden. Endlich wurde mir klar, dass der entfernte Entwickler-Server 64-Bit war und ich eine 32-Bit-Virtuelle erstellt hatte. Ich habe gerade eine 64-Bit-Virt erstellt und konnte die Datenbank lokal laden.

3
Ryan Olson

Ich habe diesen Fehler gerade umgangen, indem ich die Werte der "Länge" in der ursprünglichen Datenbank auf die Summe von ungefähr "1000" geändert habe, indem ich ihre Struktur geändert und diese dann auf den Server exportiert habe. :)

2

Ich hatte das gleiche Problem, mit dem ich es anhand der folgenden Abfrage behoben habe.

Beim Erstellen der Datenbank können Sie die UTF-8-Codierung verwenden

z.B. create database my_db character set utf8 collate utf8_bin;

1
Sudhir Dhumal