Som @Devart säger, den totala längden på ditt index är för lång.
Det korta svaret är att du inte borde indexera så långa VARCHAR-kolumner ändå, eftersom indexet kommer att vara mycket skrymmande och ineffektivt.
Det bästa är att använda prefixindex så du indexerar bara en vänster delsträng av data. De flesta av dina data kommer ändå att vara mycket kortare än 255 tecken.
Du kan deklarera en prefixlängd per kolumn när du definierar indexet. Till exempel:
...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...
Men vad är den bästa prefixlängden för en given kolumn? Här är en metod för att ta reda på det:
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`;
Den talar om andelen rader som inte har mer än en given stränglängd i menu_link
kolumn. Du kanske ser utdata så här:
+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
| 21.78 | 80.20 | 100.00 | 100.00 |
+---------------+---------------+---------------+----------------+
Detta säger att 80 % av dina strängar är mindre än 20 tecken, och alla dina strängar är mindre än 50 tecken. Så det finns inget behov av att indexera mer än en prefixlängd på 50, och absolut inget behov av att indexera hela längden på 255 tecken.
PS:INT(1)
och INT(32)
datatyper indikerar ett annat missförstånd om MySQL. Det numeriska argumentet har ingen effekt relaterad till lagring eller det tillåtna värdeintervallet för kolumnen. INT
är alltid 4 byte, och det tillåter alltid värden från -2147483648 till 2147483647. Det numeriska argumentet handlar om utfyllnad av värden under visning, vilket inte har någon effekt om du inte använder ZEROFILL
alternativ.