技术分享 | MySQL 索引长度限制的案例

MySQL前缀索引上限案例分析 一、案例分享 1.1 问题描述 以下一例报错是开发同学通过框架初始化创建一些表结构时出现的报错,我们需要重点关注“1071 Specified key was too long; max key length is 7671071 Specified key was too long; max key length is 767 bytes”这个提示。该报错告诉我们索引长度超过的额767,因过长而无法创建索引。这也是为什么经常在一些MySQL的SQL审批中,DBA同学会经常要求某个表的字段长度尽量不要超过1 阅读详情

作者:刘晨

网名 bisal ,具有十年以上的应用运维工作经验,目前主要从事数据库应用研发能力提升方面的工作,Oracle ACE ,拥有 Oracle OCM & OCP 、EXIN DevOps Master 、SCJP 等国际认证,国内首批 Oracle YEP 成员,OCMU 成员,《DevOps 最佳实践》中文译者之一,优快云 & ITPub 专家博主,公众号"bisal的个人杂货铺",长期坚持分享技术文章,多次在线上和线下分享技术主题。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


前两天同事提了一个问题,MySQL 5.7 中给某张表字段增加一个单键值索引,提示了如下错误,

一些背景信息:

  1. 表设置的字符集,utf8mb4 。
  2. 表的存储引擎,MyISAM 。
  3. 表的数据量,1个亿 。
  4. 执行的 SQL,select c1, c2 from test where c1 = :1,c1数据类型是varchar(255) ,区分度较高,需要创建一个单键值索引。

我们知道,MySQL 和 Oracle 在索引上最大的一个区别,就是索引存在长度的限制。如果是超长键值,可以支持创建前缀的索引,顾名思义,取这个字段的前多少个字符/字节作为索引的键值。

之所以可以定义一个字段前缀作为键值,存储效率是考虑的一个因素,如果列名的前10个字符通常都是不同的,检索这10个字符创建的索引应该会比检索整个列作为索引的效率更高,使用列前缀作为索引会让索引树更小,不仅节省空间,还可能提高插入操作的速度。

对于非二进制的字符串类型(CHAR、VARCHAR、TEXT),前缀会按照字符个数计算,对二进制的字符串类型(BINARY、VARBINARY、BLOB),前缀会按照字节个数计算,因此,当对非二进制的字符串列明确前缀长度的时候,需要考虑多字节字符集的因素。

MySQL 官方手册索引的章节提到了,前缀索引长度限制是和引擎相关的,如果用的是 InnoDB ,前缀上限是 767 字节,当启用 innodb_large_prefix 时,上限可以达到 3072 字节。如果用的是 MyISAM,前缀上限是 1000 字节,这正是上述创建索引错误提示的内容,

Prefix support and lengths of prefixes (where supported) are storage engine dependent. For example, a prefix can be up to 767 bytes long for InnoDB tables or 3072 bytes if the innodb_large_prefix option is enabled. For MyISAM tables, the prefix length limit is 1000 bytes.

https://dev.mysql.com/doc/refman/5.7/en/create-index.html

utf8mb4 是 MySQL 5.5.3 之后增加的编码,mb4 就是 most bytes 4 的意思,专门用来兼容四字节的 unicode ,utf8mb4 是 utf8 的超集。之所以需要 utf8mb4 ,是因为之前的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff ,也就是 Unicode 中的基本多文种平面(BMP)。因此,任何不在基本多文本平面的 Unicode 字符,都无法使用 MySQL 的 utf8 字符集存储,这就包括 Emoji 表情( Emoji 是一种特殊的 Unicode 编码,常见于手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等(这些都是 utf8 的缺点)。

InnoDB,如果需要建索引,就不能超过 767bytes ,utf8 编码,2553=765 bytes ,是能建索引情况下的最大值,utf8mb4 编码,默认字符长度则应该是767除以4向下取整,就是191。如果设置了innodb_large_prefix,最大长度是3072字节,utf8编码,10243=3072 bytes,utf8mb4编码,768*4=3072。

MyISAM,如果需要建索引,就不能超过 1000bytes ,utf8 编码,333*3=999 bytes,是能建索引情况下的最大值,utf8mb4编码,默认字符长度则应该是1000除以4,就是250。

我们可以测下 MyISAM ,utf8mb4 编码表 test1 ,250长度的字段 c1 ,251长度的字段c2 ,

CREATE TABLE test1 (  c1 varchar(250),  c2 varchar(251)) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

c1能创建索引,c2创建出错,utf8mb4编码,varchar最大限制250个字符,

/* 可执行 */
create index idx_test1_01 on test1(c1);
/*SQL 错误 [1071] [42000]: Specified key was too long; max key length is 1000 bytes*/
create index idx_test1_02 on test1(c2);

utf8编码表test2,333长度的字段c1,334长度的字段c2,

CREATE TABLE test2 (  c1 varchar(333),  c2 varchar(334)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

c1能创建索引,c2创建出错,utf8编码,varchar最大限制333个字符,

/* 可执行 */
create index idx_test2_01 on test2(c1);
/*SQL 错误 [1071] [42000]: Specified key was too long; max key length is 1000 bytes*/
create index idx_test2_02 on test2(c2);

其他场景的测试相近,不再展示。

因此,针对这个问题,可以为c1字段创建一个前缀索引,

create index idx_test_01 on test(c1(250(含)以下的值))

但是1亿数据量,创建非常慢,

通过沟通,了解到这个需求是检索今年的数据,表中存在时间戳的字段,且今年的数据,是1000多万,如果能改应用SQL,或者只是通过手工执行SQL的前提下,可以有几种解决方案:

  1. 如果从原表检索,可以创建一个c1和时间戳字段的复合索引,利用索引扫描,定位所需数据。
  2. 如果不需要从原表检索,可以使用时间戳作为条件,通过CTAS,创建一张今年数据的表,通过c1单键值索引,即可定位数据。
保姆级教程:用LoRA微调Chinese-Mistral-7B模型,并一键部署到Ollama(附完整代码) 本文提供了一份详细的LoRA微调Chinese-Mistral-7B模型的保姆级教程,涵盖环境配置、数据预处理、微调实战、模型量化及Ollama部署全流程。通过实战案例和完整代码,帮助开发者快速构建专属中文大模型,适用于医疗、法律等垂直领域。 阅读详情

相关推荐

C#与发那科机器人通信实战:从SDK配置到机械臂控制

本文详细介绍了如何使用C#与发那科机器人进行通信,从SDK配置到机械臂控制的完整实战流程。内容包括环境准备、通信连接建立、机械臂运动控制、异常处理与状态监控,以及高级功能实战,帮助开发者快速掌握工业机器人编程技术。

weixin_42524276的博客 458

mysql InnoDB引擎索引超过长度限制

组合索引长度之和大于 767 bytes并无影响,当有某个字段定义长度大于 767 bytes(1000*3)时,仅产生告警,但不影响创建,超长字段会取前 255 字符作为前缀索引,并且组合索引中字段出现的顺序并无关系。为什么3072InnoDB一个page的默认大小是 16 k。由于是Btree组织,要求叶子节点上一个page至少包含两条记录(否则就退化链表了)。所以一个记录最多不能超过 8 k...

weixin_39372979的博客 4772

3分钟!教会你用 DeepSeek/Claude3.7+Cursor 快速入门AI编程(喂饭级教程)

3分钟!教会你用 DeepSeek/Claude3.7+Cursor 快速入门AI编程(喂饭级教程)

yizhen91y的博客 4723

索引长度

在设置 utf8mb4 字段的字符长度时,可能会抛出一个异常:"Specified key was too long; max key length is 1000 bytes"。也就是在给表的索引字段添加字符长度时,超过了最大索引长度 1000 字节。 一、原因分析 关于索引长度的限制,最主要的因素就是存储引擎和字符集。 字符集的影响在于,不同的字符集,单个字符包含的最大字节数有所不同。比如 utf8 字符集,一个字符最多包含 3 个字节。而 utf8mb4 一个字符最多包含 4 个字节。 对于 In

Meiko记录 3513

【AI落地】AI生成测试用例,claude or gpt?(提效至少 50%)

gpt生成测试用例?当然好使啦,用好了提效50%+,用不好就让他变好!

青禾tester 1969

软件项目质量管理

识别项目中涉及质量管理的不同角色,如项目经理、质量经理、测试人员等,明确每个角色的职责和任务,包括负责哪些质量管理活动和决策。1、编制软件项目的质量管理计划,包括确定项目的质量标准和要求,以及制定质量控制和质量保证策略等。2、编制软件项目的质量管理计划,包括确定项目的质量标准和要求,以及制定质量控制和质量保证策略等。测试用例表是质量控制过程中的关键工具,确保所有功能和场景都被验证,减少项目中的缺陷。1、理解项目质量管理的基本过程,包括质量计划、质量保证、质量控制和质量改进;明确质量管理活动中的角色和职责。

weixin_51996255的博客 1258

MySQL索引长度限制

索引 TextField是不支持建立索引的 MySQL对索引字段长度有限制 innodb引擎的每个索引列长度限制为767字节(bytes),所有组成索引列的长度和不能大于3072字节 myisam引擎的每个索引列长度限制为1000字节,所有组成索引列的长度和不能大于1000字节 varchar的最大长度是指字符长度,若数据库字符集为utf-8,则一个字符占3个bytes。因此在utf-8字符集下,innodb引擎创建的单列索引长度不能超过255个字符 mysql版...

u011250186的博客 2952

Android GWP-Asan机制详解

基本用途:GWP-ASan是一种原生内存分配器功能,在内存分配时额外记录一些信息,用于检测DOUBLE_FREE、USE_AFTER_FREE、INVALID_FREE、BUFFER_OVERFLOW、BUFFER_UNDERFLOW五种内存错误问题。

专注于系统快稳省领域 4143

mysql 索引长度限制_修改Mysql索引长度限制

mysql 索引过长1071-max key length is 767 byte问题create table: Specified key was too long; max key length is 767 bytes原因数据库表采用utf8编码,其中varchar(255)的column进行了唯一键索引而mysql默认情况下单个列的索引不能超过767位(不同版本可能存在差异)于是utf8字...

weixin_42115003的博客 3743

Python赋能,洞见先机:构建基于异步爬虫与流处理的实时舆情监控系统

我们将从核心概念入手,逐步搭建一个集。.option("es.resource", "public-opinion-%s" % time.strftime("%Y-%m-%d")) \ # 按日期分索引。| 数据采集层 |----->| 消息队列层 |----->| 流处理与分析层 |----->| 存储与可视化层 |:使用Spark Streaming的状态操作或Flink的CEP库,检测更复杂的模式,如“某关键词的负面舆情在1小时内激增500%”。

2201_76125261的博客 434

深入详解DICOM医学影像定位线相关知识:理解定位线的概念、定位线的作用以及定位线显示和计算原理

深入详解DICOM医学影像定位线相关知识:理解定位线的概念、定位线的作用以及定位线显示和计算原理

编程技术探索者,分享C/C++、C#、Java、数据库等开发经验,聚焦实战技巧与AI兴趣,助力编程爱好者成长。 2052

小白学习MySQL - 索引键长度限制的问题

最近在工作中,碰到了个很诡异的问题,需求是在两个MySQL数据库为同一张表增加一个二级索引(单键值字段(x varchar(500))),表结构和加索引的语法,都是相同的,但是一个库执行成...

bisal的专栏 3047

Docker(八):Docker Compose(容器编排) 管理多容器应用—实战案例演示

🟢 Docker(八):Docker Compose(容器编排) 管理多容器应用—实战案例演示

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 6万+

AI如何解决MySQL索引长度限制问题

当使用UTF8MB4字符集(每个字符最多占4字节)时,一个VARCHAR(255)字段就可能达到1020字节,远超限制。这个错误通常出现在创建或修改表索引时,索引键的总长度超过了MySQL的限制。:如果业务允许,将字段字符集改为占用空间更小的格式,如从UTF8MB4改为UTF8或latin1。例如,UTF8MB4字符集的VARCHAR(n)字段,最大长度为n*4字节。:对于可能超限的索引,AI会考虑多种优化方案,并评估每种方案的优缺点,优先推荐对业务影响最小的方案。:只对字段的前N个字符建立索引。

EmeraldEagle36的博客 935

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

mysql max key length 修改索引长度限制

我整理的一些关于【MySQL,SQL】的项目学习资料(附讲解~~)和大家一起分享、学习一下:https://edu.51cto.com/surl=QDW3g3如何修改MySQL的最大索引长度 在使用MySQL数据库时,可能会遇到因为索引长度限制而导致的错误。这篇文章将帮你了解如何修改MySQL最大索引长度限制。我们将通过...

weixin_30905039的博客 561

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

MySQL新手必看:索引长度限制的通俗解读

可以快速验证各种索引配置,它的交互式界面让测试变得非常简单。我实际操作发现,平台的一键运行功能特别适合用来测试不同字符集和字段组合下的索引长度,省去了本地配置环境的麻烦。希望这篇文章能帮助MySQL新手们理解索引长度的限制。记住,好的索引设计不仅能避免错误,还能显著提升数据库性能。作为一个新手,刚开始完全摸不着头脑。经过一番摸索和实践,终于搞明白了这个问题,现在把经验分享给大家。MySQL对索引的长度是有限制的,InnoDB引擎下最大允许3072字节。

MoonbeamRaven28的博客 405

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

mysql 索引长度计算_面试官:如何精确计算mysql数据库索引长度?

概述我们知道MySQL Innodb 对于索引长度的限制为 767 字节,并且UTF8mb4字符集是4字节字符集,则 767字节 / 4字节每字符 = 191字符(默认索引最大长度),所以在varchar(255)或char(255) 类型字段上创建索引会失败,提示最大索引长度为767字节。那么怎么去计算mysql数据库索引长度呢?实验测试先看网上一道题目,针对表t,包含了三个字段a、b、c,假设...

weixin_31965935的博客 1370

告别767字节限制:用快马AI智能解决MySQL索引长度难题

部署后效果超出预期——用户粘贴SQL语句后,0.5秒内就能看到标红的高风险字段和具体优化建议。这个案例让我意识到,用好智能开发平台,真的能把恼人的技术难题变成提升效率的利器。这个错误让不少开发者头疼,尤其是使用UTF-8等多字节字符集时。下面分享我是如何通过快马平台快速构建解决方案的。最近在开发一个数据库设计助手应用时,遇到了经典的MySQL索引长度限制问题——- AI辅助生成核心的正则表达式匹配规则,快速提取SQL结构。- 直接通过网页完成所有开发,无需配置本地数据库环境。

AgatePanther34的博客 350

mysql索引技术_技术分享:Mysql索引详细介绍

原标题:技术分享:Mysql索引详细介绍 Mysql索引概述所有MySQL列类型可以被索引。对相关列使用索引是提高SELECT操作性能的最佳途径。根据存储引擎定义每个表的最大索引数和最大索引长度。所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。大多数存储引擎有更高的限制。在MySQL 5.1中,对于MyISAM和InnoDB表,前缀可以达到1000字节长。请注意前缀的限制应以字节...

weixin_32377497的博客 156

Mysql的BTree索引的原则和限制

这是自己在阅读《高性能MySQL》所做的笔记,和大家分享下 当人们谈论索引时,没有特别指明类型,那么多半就是B-Tree索引,它使用树形结构来存储数据,大多数MySQL引擎都支持这种索引类型,比如InnoDB使用的是B+Tree,Archive引擎是一个例外,它不使用任何索引。 B-Tree 索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取数据,取而代之的是从索引的根

肖斌 的专栏 3109

搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?

你采用不同的字符编码方式,对应的字节数是不一样的,比如我们最常用的 utf8mb4 字符集是 4 字节字符集,则 767 字节 / 4 字节每字符 = 191字符(默认索引最大长度),所以在 varchar(255) 或 char(255) 类型字段上创建索引会失败,报错会提示最大索引长度为 767 字节。其他的一些编码方式对应关系分别是:latin1 编码的,一个字符占用一个字节,gbk 编码的,一个字符占用两个字节,utf8 编码的,一个字符占用三个字节。不同的字符集,一个字符占用的字节数不同。...

m0_73088370的博客 112

mysql 可建多少索引_MySQL最多可建立多少索引和索引的限制

满意答案pldcairenkai推荐于 2020.04.01MySQL索引类型包括:一、普通索引这是最基本的索引,它没有任何限制。有以下几种创建方式:1.创建索引代码如下:CREATE INDEX indexName ON mytable(username(length));如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,...

weixin_42516575的博客 2918

oracle varchar默认长度_面试官:如何精确计算mysql数据库索引长度?

概述我们知道MySQL Innodb 对于索引长度的限制为 767 字节,并且UTF8mb4字符集是4字节字符集,则 767字节 / 4字节每字符 = 191字符(默认索引最大长度),所以在varchar(255)或char(255) 类型字段上创建索引会失败,提示最大索引长度为767字节。那么怎么去计算mysql数据库索引长度呢?实验测试先看网上一道题目,针对表t,包含了三个字段a、b、c,假设...

weixin_39547596的博客 532

mysql 32k 限制_技术分享 | MySQL 字段长度限制的计算方法

1./* 下面是函数 dict_index_too_big_for_tree 中关于 rec_max_size 计算部分的内容 */2./* 涉及到的辅助函数,下面也有相关说明 */3.4.rec_max_size = comp /* comp 为 true */5.? REC_N_NEW_EXTRA_BYTES /* rem0rec.h:52:#define REC_N_NEW_EXTRA_...

weixin_39883129的博客 275

mysql只能用一个索引_MySQL执行sql时一个表只能用到一个索引吗?

目录#1709 - Index column size too large. The maximum column size is 767 bytes.是什么原因导致的,如何处理?举几个你遇到的MySQL中的隐式转换案例你觉得理想的MySQL备份策略应该是怎样的,实际上你真正的备份策略又是怎样的,为什么会有不同,出于什么原因呢?MySQL执行sql时一个表只能用到一个索引吗?MySQL的前缀索引有...

weixin_28943105的博客 2035

mysql 行 长度_mysql text 长度

mysql text 长度mysql text 长度文章分类:数据库今天在做DB设计的时候在想用TEXT 是否能够满足将来的数据,能够出现装不下的情况。后来查询了一下官方手册得到了一个答案。一个BLOB或TEXT列,最大长度为65535(2^16-1)个字符。MEDIUMBLOBMEDIUMTEXT一个BLOB或TEXT列,最大长度为16777215(2^24-1)个字符。LONGBLOBLONG...

weixin_42465846的博客 218
上一篇: SQL审核 | SQLE-SQL审核平台体验报告
下一篇: 新特性解读 | MySQL 8.0 新密码策略(上)
爱可生开源社区
博客等级 码龄8年 1936粉丝 1004原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值