我是靠谱客的博主 受伤棉花糖,最近开发中收集的这篇文章主要介绍mysql 创建表字段长度范围_MySQL的一个表最多可以有多少个字段 ,索引最长有多长...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

创建表时报错:

> 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.

> 时间: 0.43s

● MySQL Server最多只允许4096个字段

● InnoDB 最多只能有1000个字段

● 字段长度加起来如果超过65535,MySQL server层就会拒绝创建表

● 字段长度加起来(根据溢出页指针来计算字段长度,大于40的,溢出,只算40个字节)如果超过8126,InnoDB拒绝创建表

● 表结构中根据Innodb的ROW_FORMAT的存储格式确定行内保留的字节数(20 VS 768),最终确定一行数据是否小于8126,如果大于8126,报错。

MySQL官方手册就可以查询到, 对于一行记录最大的限制是65535字节。为什么是65535?规定一行数据里面字段长度定义有64k;

有了65535的限制以后还有一个8126的限制是为什么呢?

MySQL是分两层的,MySQL Server层 + 存储引擎层。

第2个问题其实是MySQL除了在Server层做了一次限制还会在Innodb存储引擎层在做一次限制。

innodb为了保证B+TREE是一个平衡树结构,强制要求一条记录的大小不能超过一个页大小的一半。这也就是我们上面看到的第二个错误。

下面是innodb B+树的结构,我们可以想象一下二分查找时,一个页的只有一条数据会是什么样子?

每个页只有一条数据的查找就变成了链表查找了。这样就没有二分查找的意义了。

而MySQL中默认的页大小是16K,16K的一半是8196字节减去一些元数据信息就得出了8126这个数字。

8126是不是不能突破的呢?

我们这里就有个案例:按照附1的建表语句建立一个150个字段,每个字段是100个字符(特地使用了ASCII字符集,这样一个字符就是一个字节)的表。(建表语句和insert语句参见附录)

150 * 100=15000 > 8126。按照上面的说法,应该要报错的,但是各位可以在自己的数据库上试一下,

表能够建立成功,这是为什么呢?

其实MySQL在计算字段长度的时候并不是按照字段的全部长度来记的。列字段小于40个字节的都会按实际字节计算,如果大于20 * 2=40 字节就只会按40字节。

创建一个300个字段长度类型为varchar(30)的表,在创建时不会创建成功。因为varchar(30)没有超过20*2,那么总长度就是300*30=9000 > 8126就会创建失败。

● 创建一个150个字段长度类型为varchar(100)的表可以创建成功。因为varchar(100) 大于了20*2那么就只会按40计算 总长度就是150*20*2=6000 < 8126 就会创建成功。

varchar(40) uft8 理论上能建立203列(8126/40) 但是实际上只建立了 196列

mysql 支持最大索引:

mysql虽然可以创建很多字段,但是查询时我们往往有创建索引,而创建过多的字段在查询中难免也会根据查询条件,创建相应字段的索引,创建字段个数是相应的也要考虑要创建的索引数量;

mysql> CREATE TABLE `tb` (

-> `a` varchar(255) DEFAULT NULL,

-> `b` varchar(255) DEFAULT NULL,

-> `c` varchar(255) DEFAULT NULL,

-> `d` varchar(255) DEFAULT NULL,

-> `e` varchar(255) DEFAULT NULL,

-> KEY `a` (`a`,`b`,`c`,`d`,`e`)

-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

可以看到,由于每个字段占用255*3, 因此这个索引的大小是3825>3072,报错。

为什么3072

我们知道InnoDB一个page的默认大小是16k。由于是Btree组织,要求叶子节点上一个page至少要包含两条记录(否则就退化链表了)。

所以一个记录最多不能超过8k。

又由于InnoDB的聚簇索引结构,一个二级索引要包含主键索引,因此每个单个索引不能超过4k (极端情况,pk和某个二级索引都达到这个限制)。

由于需要预留和辅助空间,扣掉后不能超过3500,取个“整数”就是(1024*3)。

单列索引限制

上面有提到单列索引限制767,起因是256×3-1。这个3是字符最大占用空间(utf8)。但是在5.5以后,开始支持4个字节的uutf8。255×4>767, 于是增加了一个参数叫做 innodb_large_prefix。

这个参数默认值是OFF。当改为ON时,允许列索引最大达到3072。

可以看到默认行为是建表成功,报一个warning,并且将长度阶段为255。

注意要生效需要加row_format=compressed或者dynamic 。

如果确实需要在单个很大的列上创建索引,或者需要在多个很大的列上创建联合索引,而又超过了索引的长度限制,解决办法是在建索引时限制索引prefix的大小:

例如:create index yarn_app_result_i4 on yarn_app_result (flow_exec_id(100), another_column(50));

这样,在创建索引时就会限制使用的每个列的最大长度。如上的例子中,在创建联合索引时,最多使用列flow_exec_id中前100个字符创建索引,最多使用another_column中前

50个字符创建索引。这样子,就可以避免索引长度过大的问题。

最后,我想说一句。我们在设计数据库时,最好不要在一个可能包含很长字符串的列上创建索引,尤其是当这个列中的字符串都很长时。如果在这类列上创建了索引,那么在创建索引时以及根据索引查询时,都会浪费很多时间在计算和存储上。有经验的设计人员应该不会这样设计数据库。

参考文档:

最后

以上就是受伤棉花糖为你收集整理的mysql 创建表字段长度范围_MySQL的一个表最多可以有多少个字段 ,索引最长有多长...的全部内容,希望文章能够帮你解决mysql 创建表字段长度范围_MySQL的一个表最多可以有多少个字段 ,索引最长有多长...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部