首页 > 数据库 >MySQL中索引创建错误的场景

MySQL中索引创建错误的场景

时间:2023-09-25 18:32:56浏览次数:54  
标签:index 场景 column TEXT bytes length 索引 prefix MySQL


同事反馈说某个MySQL数据库创建索引提示错误,模拟报错如下,

CREATE INDEX t_reg_code_idx USING BTREE ON t(reg_code)
BLOB/TEXT column 'reg_code' used in key specification without a key length

从这个提示,可以知道是给T表的reg_code字段创建一个BTREE索引,而这个reg_code列的字段类型是BLOB或TEXT,错误信息说的是需要在键的说明中有长度定义,这是什么意思?

这个库是MySQL 8.0,从官方手册,可以找到这段对Index Prefixes的说明(如下所示),意思是如果对BLOB或者TEXT列创建索引,必须指定索引的前缀长度。对于使用REDUNDANT或者COMPACT行格式的InnoDB表,索引前缀最多767个字节,对于使用DYNAMIC或者COMPRESSED行格式的InnoDB表,索引前缀的上限最多是3072个字节,如果是MyISAM表,前缀长度最多可以达到1000个字节。

https://dev.mysql.com/doc/refman/8.0/en/column-indexes.html

Index Prefixes

With col_name(N) syntax in an index specification for a string column, you can create an index that uses only the first N characters of the column. Indexing only a prefix of column values in this way can make the index file much smaller. When you index a BLOB or TEXT column, you must specify a prefix length for the index. For example:

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Prefixes can be up to 767 bytes long for InnoDB tables that use the REDUNDANT or COMPACT row format. The prefix length limit is 3072 bytes for InnoDB tables that use the DYNAMIC or COMPRESSED row format. For MyISAM tables, the prefix length limit is 1000 bytes.

Note:Prefix limits are measured in bytes, whereas the prefix length in CREATE TABLE, ALTER TABLE, and CREATE INDEX statements is interpreted as number of characters for nonbinary string types (CHAR, VARCHAR, TEXT) and number of bytes for binary string types (BINARY, VARBINARY, BLOB). Take this into account when specifying a prefix length for a nonbinary string column that uses a multibyte character set.

If a search term exceeds the index prefix length, the index is used to exclude non-matching rows, and the remaining rows are examined for possible matches.

MySQL中索引创建错误的场景_mysql

MySQL 5.7官方手册中,对索引前缀的限制有所不同,InnoDB表的索引前缀最多可以达到1000个字节(此处结合其它章节的说名和实验,我认为是错误的,应该是3072个字节),但前提是设置了innodb_large_prefix(该参数只对DYNAMIC或者COMPRESSED行格式生效,对REDUNDANT或者COMPACT行格式无效),否则只能达到767个字节。

https://dev.mysql.com/doc/refman/5.7/en/column-indexes.html

Index Prefixes

With col_name(N) syntax in an index specification for a string column, you can create an index that uses only the first N characters of the column. Indexing only a prefix of column values in this way can make the index file much smaller. When you index a BLOB or TEXT column, you must specify a prefix length for the index. For example:

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Prefixes can be up to 1000 bytes long (767 bytes for InnoDB tables, unless you have innodb_large_prefix set).

Note:Prefix limits are measured in bytes, whereas the prefix length in CREATE TABLE, ALTER TABLE, and CREATE INDEX statements is interpreted as number of characters for nonbinary string types (CHAR, VARCHAR, TEXT) and number of bytes for binary string types (BINARY, VARBINARY, BLOB). Take this into account when specifying a prefix length for a nonbinary string column that uses a multibyte character set.

If a search term exceeds the index prefix length, the index is used to exclude non-matching rows, and the remaining rows are examined for possible matches.

MySQL中索引创建错误的场景_mysql_02

因此,可以看到MySQL 5.7和8.0在InnoDB表的索引前缀长度限制的设置上有所调整,但是限制还是有,这是和Oracle等有所不同的一个特性。

可以通过实验,验证下MySQL 8.0对于前缀长度的限制,例如创建一张row format是COMPACT的InnoDB表,指定前缀长度10000,提示最大键的长度只能是767个字节,

create table test01 (
id int(30) not null auto_increment,
t_a text,
primary key(id),
index idx_t_a(t_a(10000))
) COLLATE='gbk_chinese_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT;


SQL 错误 [1071] [42000]: Specified key was too long; max key length is 767 bytes

创建一张row format是COMPRESSED的InnoDB表,指定前缀长度10000,提示最大键的长度只能是3072个字节,

create table test01 (
id int(30) not null auto_increment,
t_a text,
primary key(id),
index idx_t_a(t_a(10000))
) COLLATE='gbk_chinese_ci' ENGINE=InnoDB ROW_FORMAT=COMPRESSED;


SQL 错误 [1071] [42000]: Specified key was too long; max key length is 3072 bytes

抛开技术问题,和同事追问了下这个操作的背景,原始需求是某个厂商的ETL任务需要从源库将数据导入目标库,源库字段是VARCHAR类型,目标库定义为TEXT,才间接引起的这个问题。推测一种可能的原因,因为VARCHAR、TEXT都可以存储字符串类型的数据,所以没做区分,能存下需要的数据就可以了,另一种可能,为了图省事儿,不用关注源库和目标库字符串类型定义的长度,直接设置了TEXT类型,保证肯定能存下。

无论是何种原因,TEXT这种大字段类型,一般不推荐作为索引检索字段,因为往往它存储了很多字符,索引存储空间会占用更多,索引的区分度也会有影响。

因此,虽然这个问题表象是个技术问题,但实际上来源于不合理的设计,我们在进行应用设计、数据库设计时,如果能多考虑一些合理性,避免一些所谓的省事儿,可能在实际使用过程中就会更顺畅,事半功倍。

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"

标签:index,场景,column,TEXT,bytes,length,索引,prefix,MySQL
From: https://blog.51cto.com/u_13950417/7598107

相关文章

  • 在哪里可以找到官方的mysql容器图像?
    如果您在容器上部署MySQL,那么首要任务之一就是找到正确的镜像。有一定程度的混乱,尤其是当我们试图帮助部署有问题的人时。例如,当人们说我使用的是官方的docker镜像…这到底意味着什么?DockerHub,提供他们的官方形象(https://hub.docker.com/_/mysql),但这不是我们Oracle的MySQL团......
  • MySQL报错:Last_Errno: 1008 | Last_SQL_Errno: 1008
    MySQL报错:Last_Errno:1008|Last_SQL_Errno:1008原创HowardSir2017-05-0616:48:38博主文章分类:MySQL©著作权文章标签mysqlMySQL文章分类MySQL数据库阅读数3783©著作权归作者所有:来自51CTO博客作者HowardSir的原创作品,请联系作者获取转载授权,否则将追究......
  • 中国信通院何宝宏:开源从“通用”走向“场景化”,下一代开源正在路上
    2021年,“开源”被首次写入国家“十四五”规划,开源凭借开放、协作、共享的特点,已成为全球软件开发和产业创新发展的主导协作模式,为信息技术高质量发展提供了强大助力。与此同时,新一代人工智能、大数据、云计算、工业互联网、区块链等技术领域正结合开源,呈现出技术与产业协同共进共融......
  • mysql备份常用方案及使用
    mysql中一个表的字段删除如果需要备份的话,有几种方案,以及选择哪一种方案MySQL是一种流行的关系型数据库管理系统(RDBMS),在生产环境中被广泛使用。对MySQL数据库进行备份是非常重要的,以防止数据丢失或损坏。以下是几种常见的MySQL备份方案及其使用场景。1.mysqldump命......
  • yum安装mysql8
    记录一下安装过程用于后面项目参考目录说明安装步骤yum安装默认目录修改默认的数据目录必要的my.cnf属性修改卸载Mysql说明一般情况下都是docker安装,部分特殊情况下,例如老外的项目部分禁用docker,那一般二进制安装或者yum直接安装。安装操作系统redhat7.xmysql版本8.0.22安装方......
  • HarmonyOS 4.0 实况窗上线!支付宝实现医疗场景智能提醒
    本文转载自支付宝体验科技,作者是蚂蚁集团客户端工程师博欢,介绍了支付宝如何基于HarmonyOS4.0实况窗实现医疗场景履约智能提醒。1.话题背景8月4日,华为在HDC(华为2023开发者大会)上推出了新版本操作系统HarmonyOS4.0,主打个性化与多元化的的口号。在功能介绍环节,支付宝依托......
  • mysql学习
    mysql0.数据库常见概念0.1概念数据库:英文单词DataBase,简称DB。按照一定格式存储数据的一些文件的组合。顾名思义:存储数据的仓库,实际上就是一堆文件。这些文件中存储了具有特定格式的数据。数据库管理系统:DataBaseManagement,简称DBMS。数据库管理系统是专门用来管理......
  • MySQL实战实战系列 07 行锁功过:怎么减少行锁对性能的影响?
    在上一篇文章中,我跟你介绍了MySQL的全局锁和表级锁,今天我们就来讲讲MySQL的行锁。 MySQL的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如MyISAM引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只......
  • MySQL——处理JSON类型的数据
    MySQL对JSON类型数据的处理参考视频:快速学习MySQL8JSON注意,本文的键名也可以叫key,键值也可以叫value,意思是一样的1.字符串查询:JSON_EXTRACT假设我们有一个表叫做testDemo,其中有一个字段叫做details,类型为JSON,他的数据结构如下,我们就以这个结构为例(这是个例子,假设有很多行......
  • MySQL 索引、事务与存储引擎
    MySQL索引、事务与存储引擎---MySQL索引---1.索引的概念●索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址)。●使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数......