Comme dit, la longueur totale de votre index est trop longue.
La réponse courte est que vous ne devriez de toute façon pas indexer des colonnes VARCHAR
aussi longues, car l'index sera très volumineux et inefficace.
La meilleure pratique est d'utiliser des index de préfixe afin de n'indexer qu'une sous-chaîne de données. La plupart de vos données seront de toute façon beaucoup plus courtes que 255 caractères.
767 octets est la limitation de préfixe indiquée pour les tables InnoDB
- elle est de 1 000 octets de long pour les tables MyISAM
.
En fonction de la réponse à ce problème, vous pouvez obtenir la clé à appliquer en spécifiant un sous-ensemble de la colonne plutôt que la quantité totale. Cela signifie que vous pouvez déclarer une longueur de préfixe par colonne lorsque vous définissez l'index.
Par exemple:
KEY `nom_de_la_cle` (`action_id`(50),`module_id`(50))
Voici un exemple pour expliquer cela plus clairement : J'ai créé une table et y ai inséré des données.
CREATE TABLE `phppos_modules_actions` (
`action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`sort` INT NOT NULL ,
PRIMARY KEY ( `action_id`(50) , `module_id`(50) )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Mais quelle est la meilleure longueur de préfixe pour une colonne donnée ? Voici une méthode pour le découvrir :
SELECT
ROUND(SUM(LENGTH(`action_id`)<10)*100/COUNT(*),2) AS pct_length_10,
ROUND(SUM(LENGTH(`action_id`)<20)*100/COUNT(*),2) AS pct_length_20,
ROUND(SUM(LENGTH(`action_id`)<50)*100/COUNT(*),2) AS pct_length_50,
ROUND(SUM(LENGTH(`action_id`)<100)*100/COUNT(*),2) AS pct_length_100
FROM `phppos_modules_actions`;
+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
| 42.86 | 80.20 | 100 | 100 |
+---------------+---------------+---------------+----------------+
Cela vous indique que 80 % de vos chaînes sont inférieures à 20 caractères, et que toutes vos chaînes sont inférieures à 50 caractères. Il n'est donc pas nécessaire d'indexer plus qu'une longueur de préfixe de 50, et certainement pas nécessaire d'indexer sur la longueur totale de 255 caractères.
Ajustez comme vous en avez besoin pour que la clé s'applique, mais je me demande s'il ne serait pas utile de revoir votre modèle de données concernant cette entité pour voir s'il existe des améliorations qui vous permettraient de mettre en œuvre les règles métier prévues sans atteindre la limitation de MySQL.
Des alternatives aux paramètres dans InnoDB peuvent être trouvées sur http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/