首页 > 数据库 >MySQL一张表最多添加多少个text字段?

MySQL一张表最多添加多少个text字段?

时间:2023-09-03 11:01:12浏览次数:65  
标签:建表 字节 text 197 插入 字段 MySQL page

1背景

当用户从 oracle 迁移到 MySQL 时,可能由于原表字段太多建表不成功,这里讨论一个问题:一个 InnoDB 表最多能建多少个 text 字段。

我们后续的讨论基于创建表的语句形如:create table t(f1 text, f2 text, …, fN text)engine=innodb;

1.1「默认配置」

在默认配置下,上面的建表语句,N 取值范围为[1, 1017]。

为什么是 1017 这个“奇怪”的数字?

实际上单表的最大列数目是 1024-1,但是由于 InnoDB 会增加三个系统内部字段(主键 ID、事务ID、回滚指针),因此需要减3。而用于记录系统字典表也受 1023 的限制,又需要再增加三个该表的系统字段,因此每个表的最大字段数是 1023 - 3 * 2。

1.2「插入异常」

上述描述说明的是表能够创建成功的最大字段数。但是这样的表是“插入不安全”的。我们知道 text 的长度上限是 64k。而往上表中插入一行,每个字段长度为 7,就会报错:Row size too large (> 8126)

一个 page 是 16k,空 page 扣掉页信息占用空间是 16252,需要除以 2,原因是每个 page 至少要包含两个记录。

也就是说,虽然可以创建一个包含 1017 个 text 字段的表,但是很容易碰到插入失败。

1.3「如何保证插入安全」

上面的表结构,在保证插入安全的情况下,N 的最大值是多少?

text 在存储的时候,当超过 768 字节的时候,剩余部分会保存在另外的页面(off-page),因此每个字段占用的最大空间为 768 + 20 + 2 = 788. 20 字节存储最短剩余部分的位置(SPACEID+PAGEID+OFFSET)。2 字节存储本地实际长度。

因此 N 最大值为 lower(8126 / 790) = 10。

如果我们想在创建的表的时候,保证创建的表中的 text 字段都能安全的达到 64k 上限(而不是等插入的时候才发现),那么需要将默认为 OFF 的 innodb_strict_mode 设置为 ON,这样在建表时会先做判断。

但是,在设置为严格模式后,上述建表语句的最大 N 却并非 10。

2ROW_FORMAT

在 off-page 存储时,本地占用790个字节,是基于默认的 ROW_FORMAT,即为 COMPACT,此时插入安全的 N 上限为 10。

而在 InnoDB 新格式 Barracuda 支持下,Dynamic 格式的 off-page 存储时,在 local 保存的上限不再是 768,而是 20 个字节。这样每个字段在数据页里面占用的最大值是 40byte,再需要一个额外的字节存储实际的本地长度,因此每个 text 最大占用 41 字节。

实际上很容易测试在严格模式下,建表的最大 N 为 196。以下为 N=197 时计算过程:

  • 每行记录预留header 5个字节。
  • 每个bit保存是否允许null,需要 upper(197/8)=25个字节。
  • 三个系统保留字段 6+6+7=19.

因此总占用空间:5+25+19+41*197=8126!

也就是说,当 N=197 时,刚好长度为 8126,而代码中实现是if(rec_max_size >= page_rec_max) reutrn(error)

就这么不巧!

3作为补充

有经验的读者可以联想到,如果我们的表中自己定义一个 int 型主键呢?此时系统不需要额外增加主键,因此整个表结构比之前少 2 字节。

也就是说,建表语句修改为: create table t(id int primary key, f1 text, f2 text, …, fN text)engine=innodb;

则此时的 N 上限能达到 197。

标签:建表,字节,text,197,插入,字段,MySQL,page
From: https://blog.51cto.com/u_16031739/7338549

相关文章

  • 在MySQL中插入数据后,对两个数值进行条件性增加
    在MySQL中,可以使用UPDATE语句对插入的数据进行条件性增加。以下是一个示例:假设有一个名为"table_name"的表,其中有两列"column1"和"column2",我们要对"column1"和"column2"的数据进行条件性增加。UPDATEtable_nameSETcolumn1=column1+10,column2=column2+5WHEREcon......
  • MySQL基础篇:掌握数据表操作的基础知识
    表(table)是一种结构化的文件,可以用来存储特定类型的数据,如:学生信息,课程信息,都可以放到表中。另外表都有特定的名称,而且不能重复。表中具有几个概念:列、行、主键。列叫做字段(Column),行叫做表中的记录,每一个字段都有:字段名称/字段数据类型/字段约束/字段长度创建表在MySQL中,......
  • 纯分享:将MySql的建表DDL转为PostgreSql的DDL
    背景现在信创是搞得如火如荼,在这个浪潮下,数据库也是从之前熟悉的Mysql换到了某国产数据库。该数据库我倒是想吐槽吐槽,它是基于Postgre9.x的基础上改的,至于改了啥,我也没去详细了解,当初的数据库POC测试和后续的选型没太参与,但对于我一个开发人员的角度来说,它给我带来的不便主要是......
  • MySQL添加用户并授权
    执行前要确认,授权给这个用户的数据库已经被创建好createdatabase库名charactersetutf8mb4;接下来,可以采用直接授权的方式,能够同时创建用户以及授权grantselect,insert,delete,update,createon库名.*to'用户名'@'%'identifiedby'密码';......
  • 重复索引检查mysql pt-duplicate-key-checker
    索引对于优化数据库中的查询执行时间至关重要,但是索引数量过多或冗余会对性能产生负面影响。虽然pt-duplicate-key-checker是识别MySQL中重复或冗余索引的首选工具,但它可能无法捕获所有重复。测试环境,mysql5.7.27建表结mysql[localhost:5727]{root}(sbtest)>CREATETABLE`sbt......
  • MYSQL数据库备份还原,并还原到最新状态(mysqldump)
    启用二进制日志文件vim/etc/my.cnf配置文件位置及文件名根据实际情况确定<br>sql_log_bin=on|off:是否记录二进制日志,默认为on在需要的时候设置为off=""<br>log_bin="/PATH/BIN_LOG_FILE:指定二进制日志文件位置;"通常单独存放到与数据库不同的机器中=""<=""p=""></br>......
  • IPV6配置mysql
    一、mysql参数影响mysql配置文件my.cnf可以配置一个参数bind-address该参数默认为*,意思是全网监听(可以是ipv4也可以是ipv6)如果该参数设置成ipv4地址,则mysql的3306端口监听ipv4地址如果该参数设置生ipv6地址,则mysql的3306端口监听ipv6地址二、mysql主从配置CHANGEMASTERTO......
  • MySQL的基本语句
    目录1.0数据库操作2.0数据表操作2.1表的创建2.2表的修改2.2.1表中字段的添加2.2.2表中字段的修改2.2.3表中字段的删除2.3表的查询2.3.1查询数据库中所有的表2.3.2查询表结构2.4表的删除2.5表中数据的操作2.5.1表数据的查询2.5.1.1表中数据的简单查询2.5.1.2表中数据......
  • CentOS6.5安装mysql 远程登录
    第1步、yum安装mysql[[email protected]]#yum-yinstallmysql-server直到出现结果: 第2步、设置开机启动[[email protected]]#chkconfigmysqldon这步没提示第3步、启动mysql服务[[email protected]]#servicemysqldstartshell提示: 第4步、修改r......
  • mysql索引(转)
    转载:https://www.php.cn/faq/493277.html一、数据结构区分1.1.B+tree索引根据存储方式,mysql可以分为B+tree索引和哈希索引B+tree索引可以进行全键值、键值范围和键值前缀查询1.2.哈希索引哈希索引也称为散列索引或 HASH索引。MySQL目前仅有MEMORY存储引擎和HEAP存......