我知道这个标题的问题以前已经被回答过了,但请继续读下go .在发布之前,我已经彻底阅读了关于这个错误的所有其他问题/答案.

对于以下查询,我得到了上述错误:

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;

有人知道为什么以及如何修复它吗?

任何线索都行.

我用的是phpMyAdmin.

推荐答案

正如@Devart所说,索引的总长度太长了.

简单的回答是,无论如何都不应该为这么长的VARCHAR列编制索引,因为索引会非常庞大且效率低下.

最好的做法是使用prefix indexes,这样就只对数据的左一个子串进行索引.不管怎样,你的大部分数据都会比255个字符短得多.

定义索引时,可以为每列声明前缀长度.例如:

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

但给定列的最佳前缀长度是多少?下面是一个方法:

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`;

它告诉您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的另一种误解.数值参数与存储或列允许的值范围无关.INT总是4字节,它总是允许从-2147483648到2147483647的值.数值参数是关于在显示期间填充值的,除非使用ZEROFILL选项,否则不会产生任何效果.

Mysql相关问答推荐

mysql查询汇总数据

找出同一表中列A中的每个值在列B中出现的次数

用于将具有多个状态更改日期列的单行转换为具有状态和时间戳的多行的SQL查询

在MySQL中使用FIRST_VALUE()

为什么我的 SQL 查询不更新 Node.js 和 MySQL 中用户以外的用户属性?

global max_connections 和 spring.hikari.maximumPoolSize 有什么区别?

从 mysql RDS 导出数据以导入 questDb

如何查询由另一个查询创建的表?

在 Codeigniter MySQL 中从另一个数据库获取数据

从多到多表中 Select 数据而无需重复

总行大小不超过 65535,但我得到行大小太大.所用表类型的最大行大小,不包括 BLOB,是 65535错误

在 SQL 中将列添加为 End_date,间隔为 +100 天

最好的 MySQL 性能调优工具?

MySQL PHP - Select WHERE id = array()?

mysql 按日期 Select 总和组

基于字符串动态创建 PHP 对象

仅在 MYSQL DATEDIFF 中显示小时数

考虑到 NodeJS,MySQL 和 MySQL2 有什么区别

警告:mysqli_connect(): (HY000/1045): Access denied for user 'username'@'localhost' (using password: YES)

在 MySQL 中仅 Select 仅包含字母数字字符的行