mysql索引长度由字段类型和字符集决定,不可手动设置;前缀索引用于避免超长索引报错,需兼顾区分度与性能,短字段无需前缀,char/varchar定义长度不等于索引长度。

MySQL 索引长度由字段类型和字符集决定,不能直接“设置”
MySQL 不提供类似 INDEX LENGTH = 100 这样的语法来手动指定索引长度。所谓“索引长度”,本质是 MySQL 对索引列实际存储字节数的计算结果,它取决于:字段定义(如 VARCHAR(255))、字符集(如 utf8mb4)、是否为前缀索引。InnoDB 要求单个索引列(或前缀)长度不超过 767 字节(innodb_large_prefix=OFF 时),或 3072 字节(ON 且行格式为 DYNAMIC 或 COMPRESSED)。
什么时候必须用前缀索引?
当字段是长文本(如 VARCHAR(1000))且使用 utf8mb4 字符集时,完整索引可能超限:1000 × 4 = 4000 字节 > 3072 → 报错 ERROR 1071 (42000): Specified key was too long。此时只能截取前缀:
-
CREATE INDEX idx_title ON articles (title(191));——utf8mb4下 191 字符 ≈ 191 × 4 = 764 字节,安全 - 选择前缀长度要兼顾区分度:
SELECT COUNT(DISTINCT LEFT(title, 191)) / COUNT(*) FROM articles;接近 1 才有效 - 避免对短字段(如
VARCHAR(50))加前缀——没意义,还削弱查询能力(WHERE title = 'xxx'无法走索引)
CHAR/VARCHAR 的定义长度不等于索引长度
很多人误以为 VARCHAR(255) 就会建出 255 字符的索引。实际取决于你是否显式指定前缀:
-
ALTER TABLE t ADD INDEX (name);→ 对VARCHAR(255)字段,若字符集为utf8mb4,则默认尝试索引全部 255 字符 → 255×4=1020 字节 → 在老版本或配置下直接失败 -
ALTER TABLE t ADD INDEX (name(100));→ 明确只索引前 100 字符,长度为 400 字节 -
CHAR(10)字段无论内容多短,索引长度固定为 10 × 字符字节数(utf8mb4下恒为 40 字节)
影响性能的关键不是“长度数字”,而是区分度与覆盖范围
索引太短(如 name(5))会导致大量哈希碰撞,B+ 树底层节点重复值多,扫描行数暴增;索引太长(如 content(1000))不仅占更多 Buffer Pool,还会让二级索引页更少容纳记录,降低缓存效率。实操建议:
- 用
SHOW INDEX FROM table_name;查看Sub_part列:非 NULL 表示用了前缀索引,数值即前缀长度 - 用
SELECT data_length / index_length FROM information_schema.tables WHERE table_name = 't';辅助判断索引膨胀是否异常 - 对 JSON 字段或超长 URL,优先考虑生成哈希字段(
url_hash CHAR(32) AS (MD5(url)) STORED)再建索引,比前缀更可控
真正难的是在业务模糊匹配需求(如 LIKE '%关键词%')和索引物理限制之间找平衡点——这时候前缀索引往往只是权宜之计,该上全文索引或 Elasticsearch 就别硬扛。











