当前位置: 首页 > news >正文

MySQL索引 Error1071

MySQL创建索引错误 Error 1071:Specified key was too long

目录

  • 1. 起因
  • 2. 使用环境
  • 3. 查找问题的原因
  • 4. 解决方案
  • 5. 另外的解决方案
  • 6. 前缀索引

起因

事情的起因在一次生产环境部署启动服务,发现启动服务时间特别长,超过了5分钟的时间。于是,连接上服务器查看了启动的日志,发现有多个如下错误:

Error 1071:Specified key was too long; max key length is 767 bytes.

直白的讲,这个错误的原因是创建索引的字段长度,超过了最大的限制767byte,因此创建失败。

使用环境

MySQL:5.7.24
引起:InnoDB

查找问题的原因

首先,根据错误的提示查看了出错的表的索引字段的类型:

# desc tableName
Field	Type            Null    Key
BE_ID	varchar(300)    YES	MUL

发现创建索引的字段BE_ID长度为varchar(300),创建的索引为非主键索引。紧接着,查看了数据表使用的字符集:

# show table status from dbName like 'tableName'
Name        Engine  Version    Collation
tableName   InnoDB  10         utf8_general_ci

我们知道,utf-8字符集每个字符占用1~3个字节不等,但是MySQL在计算最大长度时,在不知道数据长度的情况下只能用3个字节进行计算(个人推断),因此300个字符至少需要300*3=900的长度才能创建出来索引,而我们使用的当前数据库所有的最大长度限制为767,因此超长了,创建索引错误也在所难免。

解决方案

既然找到的原因,那么我们是不是尝试去掉这个限制就可以了呢?经过一番网上查找,发现MySQL有个开关innodb_large_prefix就是控制这个长度的。

innodb_large_prefixonoff
最大长度3072767

查看我自己的数据库,发现其状态确实是关闭状态,打开后也确实能解决此问题,于是有可以愉快的开始写bug!

另外的解决方案

打开innodb_large_prefix的开关后,确实解决了此次的问题,但是这确实是唯一的正确的解吗?不一定是的,从数理上来看,既然你超过了最大长度限制,那么减小你的索引长度是不是也是一种方案呢?

是的,后经仔细的排查,发现在字段BE_ID的长度根本不需要300字符,120个就是极限情况了,因此若吧varchar(300)=>varchar(120),同样可以解决这里的问题。后来,经开发同学回忆(因为时间太久),可能是考虑了未来某种扩容的情况,因此给的长度比较大,而实际上已经过去3年了,仍然没有这种扩容字段的情况发生!

那如果BE_ID的长度确确实实需要300的长度呢,我们还有什么别的办法吗?还是有点,那就是前缀索引

前缀索引

前缀索引的创建方式

mysql> alter table tableName add index index_name_1(BE_ID);
或
mysql> alter table tableName add index index_name_2(BE_ID(20));
  • index_name_1: 普通索引,即使用BE_ID全字符串作为索引对象;
  • index_name_2: 前缀索引,即只使用BE_ID字符串的前20位作为索引对象;
    前缀索引,不光能解决创建索引超长的问题,也能减少索引的存储空间。但是前缀索引也不是完全没有代价的:会增加查询的扫码次数,并且不能使用覆盖索引。前缀索引会存在前缀区分度不够的情况,比如身份证的前6位,同一个县的完全一致,这时候和不用索引没甚区别了。

解决前缀索引区分度不够的问题,可以考虑倒序存储或者hash字段索引等方式,但同样也会引入其他问题,比如不支持范围扫描等。因此需要慎用!

总结:合适的才是最好的!

相关文章:

  • 基于单片机的温湿度检测系统设计
  • 遥遥领先!TinyEngine 低代码引擎更新升级!AI 已成功部署!
  • JMeter 设置请求头信息的详细步骤
  • ⑦【Redis GEO 】Redis常用数据类型:GEO [使用手册]
  • centos7卸载mongodb数据重新安装时无法安装的问题
  • 3.1 CPU内部结构与时钟与指令
  • Vite CSS Module 优雅的处理样式隔离
  • R数据分析:集成学习方法之随机生存森林的原理和做法,实例解析
  • CentOS 7实现类似于Kali Linux中的自动补全功能
  • css实现图片绕中心旋转,鼠标悬浮按钮炫酷展示
  • 在两个java项目中实现Redis的发布订阅模式
  • 车载电子电器架构 ——电子电气架构设计方案概述
  • 【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析模拟实现
  • Linux云服务器打包部署前端Vue项目
  • 从零开始,用Docker-compose打造SkyWalking、Elasticsearch和Spring Cloud的完美融合
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Apache的80端口被占用以及访问时报错403
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • JAVA 学习IO流
  • Joomla 2.x, 3.x useful code cheatsheet
  • js数组之filter
  • Python 基础起步 (十) 什么叫函数?
  • tab.js分享及浏览器兼容性问题汇总
  • webpack项目中使用grunt监听文件变动自动打包编译
  • WebSocket使用
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 分布式任务队列Celery
  • 分享一份非常强势的Android面试题
  • 服务器之间,相同帐号,实现免密钥登录
  • 马上搞懂 GeoJSON
  • 收藏好这篇,别再只说“数据劫持”了
  • Linux权限管理(week1_day5)--技术流ken
  • Spring Batch JSON 支持
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #define,static,const,三种常量的区别
  • (安卓)跳转应用市场APP详情页的方式
  • (二)windows配置JDK环境
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (四)JPA - JQPL 实现增删改查
  • (一)VirtualBox安装增强功能
  • (转)视频码率,帧率和分辨率的联系与区别
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .form文件_SSM框架文件上传篇
  • .Net Web窗口页属性
  • .net 简单实现MD5
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .net生成的类,跨工程调用显示注释
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @JSONField或@JsonProperty注解使用
  • @取消转义
  • [ vulhub漏洞复现篇 ] Jetty WEB-INF 文件读取复现CVE-2021-34429
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)
  • [17]JAVAEE-HTTP协议
  • [2010-8-30]