如何将 ROW_FORMAT=DYNAMIC 应用于现有表

Dan*_*anH 5 mysql innodb longtext

我有一个包含大量长文本字段 (18) 以及许多其他各种整数和 varchar 字段的表。最近添加了一些额外的长文本字段,突然迫使我了解有关 8K 行大小限制的所有信息。数据库运行的是 Mysql 5.6.34,有问题的表当前是 Antelope / ROW_FORMAT=COMPACT。

我的理解是,在这种格式中,每列每行最多占用 768 个字节,直到溢出到单独的存储中。当太多的各种长文本获取大量数据时,这会导致我出现此错误:

行大小太大 (> 8126)。将某些列更改为 TEXT 或 BLOB 或使用 ROW_FORMAT=DYNAMIC 或 ROW_FORMAT=COMPRESSED 可能会有所帮助。在当前行格式中,768 字节的 BLOB 前缀是内联存储的。忽略表中的其余字段,如果所有 18 个长文本均为 768 字节,则主索引将为所有字段存储 13,824 字节。

我尝试将表更新为 ROW_FORMAT=DYNAMIC,期望这会将长文本的溢出阈值从 768 字节降低到仅 20 字节,因此应将所有长文本字段的最大主索引存储要求降低到 18 * 20 = 360 字节。我尝试按照以下方式进行更新:

ALTER TABLE mytable ROW_FORMAT=DYNAMIC;
OPTIMIZE TABLE mytable;
Run Code Online (Sandbox Code Playgroud)

没有错误并输出以下内容:

mydb.mytable 优化注意表不支持优化,改为重新创建+分析 mydb.mytable 优化状态 OK

如果我查看表的 CREATE TABLE 语法,我可以看到设置了 ROW_FORMAT=DYNAMIC。

然后,我尝试编写一行来填充所有长文本列,每个列大约 5.7kb,但是在阻止保存该行之前我只能填充其中的 10 个,并且 10 * 768 = 7,680 字节,在计算时其他非长文本必填字段非常接近 8kb 限制,表明 ROW_FORMAT=DYNAMIC 指令不适用于现有行。

我并不是特别希望通过转储/导入来重新创建数据库,但是因为它特别大,并且会代表延长的服务停机时间,我不确定在用尽其他选项之前是否可以证明这一点。

Ric*_*mes 9

(这个答案虽然集中于索引,但很可能解决您的问题。)

http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes

处理 767 限制有 5 种选择。这似乎就是您需要的

   SET GLOBAL innodb_file_format=Barracuda;
   SET GLOBAL innodb_file_per_table=1;
   SET GLOBAL innodb_large_prefix=1;
   logout & login (to get the global values);
   ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- (or COMPRESSED)
Run Code Online (Sandbox Code Playgroud)

(升级到 5.7.7 或更高版本是另一种解决方案 - 但这仅将上述内容设置为默认值;我认为您仍然需要执行此操作ALTER。)


Dan*_*anH 1

innodb_file_format=barracuda事实证明我需要在 ALTER/OPTIMIZE 之前设置。出于某种原因,我认为设置 DYNAMIC 也会隐式设置梭子鱼,但事实证明情况并非如此:

SET GLOBAL innodb_file_format=barracuda
Run Code Online (Sandbox Code Playgroud)