当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 不同字符集列的索引长度参数对比

MySQL 不同字符集列的索引长度参数对比

来源:17golang原创 2026-10-31 23:30:24 0浏览 收藏

这类问题通常出现在把旧表从 utf8mb3 迁移到 utf8mb4 之后:原来能创建的 INDEX(name(255)) 突然报索引过长。根因不是“255 这个参数失效”,而是 MySQL 对非二进制字符串把前缀参数按字符数解释,却按字节数检查索引上限。utf8mb4 最多使用 4 字节表示一个字符,所以同样的 255 个字符,最坏情况会占 1020 字节。

官方文档:https://dev.mysql.com/doc/refman/8.4/en/column-indexes.html

要点速览
  • 非二进制字符串的 INDEX(col(N)) 中,N 按字符数写;索引前缀上限按字节数算。
  • 保守换算公式是:安全字符数 = floor(字节上限 ÷ 字符集最大字节数)。
  • 迁移前要同时看字符集、InnoDB 行格式、联合索引的总和与前缀选择性,不能只把 255 改成 191。

影响面:同一个 255 参数为什么在迁移后失败

我在排查这类迁移错误时,先把问题拆成两个单位:DDL 中的长度是字符,存储引擎限制是字节。MySQL 文档明确说明,CHAR、VARCHAR、TEXT 的索引前缀参数按字符解释;BINARY、VARBINARY、BLOB 则按字节解释。

因此旧表若使用 utf8mb3,255 个字符按最坏情况估算为 255 × 3 = 765 字节,可以贴近 767 字节上限。转换为 utf8mb4 后,最坏情况变为 255 × 4 = 1020 字节;在 COMPACT 或 REDUNDANT 行格式下就可能触发 Specified key was too long。

MySQL 字符集最大字节数、索引前缀字符数和字节上限之间的静态关系说明图
图1:结构说明图,展示字符数参数经过字符集字节宽度换算后落到 InnoDB 索引上限的关系,不是数据库运行截图。

时间线:先按字符集换算,再对照两种常见上限

可以用下面这张保守对照表快速判断。它使用字符集的最大字节数,而不是某一批实际数据的平均字节数;这样迁移时不会因为当前样本 mostly 是 ASCII 而低估风险。

字符集最大字节/字符767 字节上限的保守前缀3072 字节上限的保守前缀
ascii / latin11767 字符3072 字符
utf8mb33255 字符1024 字符
utf8mb44191 字符768 字符
utf16最多 4按 4 字节保守估算 191 字符按 4 字节保守估算 768 字符

767 字节适用于 InnoDB 的 COMPACT 或 REDUNDANT 行格式;DYNAMIC 或 COMPRESSED 可使用到 3072 字节的前缀上限。这里的“安全前缀”是最坏字节数下的整数下取整,不代表前缀越长查询就一定越快。

-- 用表定义确认列字符集和行格式,再决定迁移参数。
SHOW CREATE TABLE customer;

-- 查看索引是否已经是前缀索引,Sub_part 对字符串表示字符数。
SHOW INDEX FROM customer;

-- 用最坏字节数做迁移前的保守估算。
-- utf8mb4 在 767 字节上限下:FLOOR(767 / 4) = 191。

触发条件:单列能算对,联合索引仍可能超限

迁移中第二个容易漏掉的点是联合索引。比如 (title(191), slug(191)) 的两个前缀都分别符合 utf8mb4 的 767 字节单列换算,但它们放在同一个索引键中时,必须按各 key part 的最坏字节数合计,再结合该存储引擎的总键长度限制判断。列字符集不同,也要分别使用各自的最大字节数。

另外,VARCHAR(255) 的列长度和 INDEX(col(191)) 的索引前缀不是同一个参数:前者决定列最多存多少字符,后者只把前 N 个字符放进索引。把列直接改成 VARCHAR(191) 会改变数据模型,只有确认业务不需要更长值时才这样做;仅为了降低索引大小,优先讨论索引前缀。

MySQL 联合索引中不同字符集列分别换算字节预算并汇总的静态关系说明图
图2:边界说明图,展示联合索引各列按自身字符集换算后共享键长度预算,不是执行计划或运行结果截图。

根因修复:缩短前缀、调整行格式,还是重新评估选择性

如果目标表确实是旧行格式,且业务只需要前缀查找,最小改动通常是把 utf8mb4 的前缀从 255 调整为 191,再单独评估唯一索引是否仍能满足唯一性。唯一索引不能因为超限而悄悄缩短,否则可能把原本不同的值压成相同的索引键。

如果表可以采用 DYNAMIC 或 COMPRESSED 行格式,则可以使用更大的 3072 字节预算,但这仍不是“所有索引都写 768”的理由:联合索引、实例页大小和列的实际业务区分度都需要重新核对。前缀太短会降低选择性,让 MySQL 在索引筛选后回表检查更多记录。

-- 仅示意旧表迁移;先在变更窗口确认行格式和索引用途。
ALTER TABLE customer
  MODIFY title VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL,
  DROP INDEX idx_title,
  ADD INDEX idx_title (title(191));

-- 调整后再次查看索引定义,确认前缀参数已经落在目标列上。
SHOW INDEX FROM customer WHERE Key_name = 'idx_title';

防复发:把“字符参数”与“字节预算”写进迁移清单

  • 先读 SHOW CREATE TABLE,记录每个索引列的字符集、排序规则和 InnoDB 行格式。
  • 按最大字节数计算,而不是拿现有数据样本的平均长度计算。
  • 联合索引按所有 key part 的最坏情况汇总;涉及唯一索引时,先确认缩短前缀不会破坏唯一性。
  • 前缀缩短后关注选择性;必要时改为更适合查询的列组合,而不是无条件放大索引。

常见问题

为什么 utf8mb4 常见的前缀长度是 191?

在 767 字节的旧 InnoDB 前缀上限下,按每字符最多 4 字节保守计算,floor(767 / 4) = 191。这不是 utf8mb4 的固定语法限制,而是字节上限换算结果。

实际数据大多是英文,可以按 1 字节计算吗?

不建议用于结构迁移。索引定义要能容纳列允许的最坏字符,实际值偏 ASCII 只能帮助理解平均占用,不能替代上限计算。

把行格式改成 DYNAMIC 后就不用管前缀了吗?

不用。它只把某些 InnoDB 表的前缀预算提高到 3072 字节,联合索引合计、页大小、唯一性和前缀选择性仍然要单独判断。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Redis XINFO STREAM 统计首尾消息与消费组状态Redis XINFO STREAM 统计首尾消息与消费组状态
上一篇
Redis XINFO STREAM 统计首尾消息与消费组状态
Redis HSTRLEN 怎样判断 Hash 字段值长度
下一篇
Redis HSTRLEN 怎样判断 Hash 字段值长度
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    816次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    807次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    899次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    870次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    693次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码