正如@Devart所说,你的索引的总长度太长。
简单的答案是,你不应该索引这么长的VARCHAR列,因为索引会非常庞大和低效。
最佳做法是使用前缀索引,以便只索引数据的左子字符串。你的大部分数据将大大短于255个字符。
您可以在定义索引时声明每列的前缀长度。例如:
...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...
但是给定列的最佳前缀长度是多少?这里有一个方法来找出:
SELECT
ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(*),2) AS pct_length_10,
ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(*),2) AS pct_length_20,
ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(*),2) AS pct_length_50,
ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(*),2) AS pct_length_100
FROM `pds_core_menu_items`;
它告诉你在menu_link列中有不超过给定字符串长度的行的比例。您可能会看到如下输出:
+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
| 21.78 | 80.20 | 100.00 | 100.00 |
+---------------+---------------+---------------+----------------+
这告诉你,80%的字符串少于20个字符,并且所有的字符串少于50个字符。因此,没有必要索引多于50的前缀长度,并且肯定不需要索引255个字符的全长。
PS:INT(1)和INT(32)数据类型表示对MySQL的另一种误解。 numeric参数与存储或列允许的值范围无关。 INT始终为4字节,并且始终允许值为-2147483648到2147483647.数字参数是关于显示期间的填充值,除非使用ZEROFILL选项,否则此操作无效。