微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有列的页面溢出 (InnoDB) 在 MySQL 中如何工作?

如何解决带有列的页面溢出 (InnoDB) 在 MySQL 中如何工作?

文档说:“列是否存储在页外取决于页面大小和行的总大小。”

1.- 这意味着如果我的页面大小为 16KB,则行的最大大小为 8KB,因此,如果我有 4 列,每列的最大大小是否为 2KB(大约)?

2.- 当文档说“列是否存储在页外取决于页面大小和行的总大小。”时,它仅对 DYNAMIC 和 COMPRESS 列格式有效,或者也适用于REDUNDANT 和 COMPACT 列的格式,或者当使用 REDUNDANT 和 COMPACT 时,总是使列的多余数据进入溢出页,每行的最大大小为 768 字节?它不占用该行其余部分的空闲空间吗?.

3.- 索引的大小受行和列大小的影响,也就是说,回到我在问题 1 中提出的问题,每行将是 2KB(大约),如果它有DYNAMIC 列格式的类型,最大索引大小应该是 2KB(大约 2000 字节)而不是 3072 字节,对吗?

解决方法

忘记示例中的 2KB;它具有误导性,而且大多无关紧要。

是的,16KB数据块中的内容大约有 8KB 的限制。 (后面会介绍索引块。)

列要么进入最多 8KB 的空间,要么进入另一个块(“非记录”存储)。

MySQL 决定是否将列放入 8KB 限制中

  • Datatype -- 数字列总是进入;字符串和 blob 取决于。
  • 行格式和列大小——较小的字符串和 blob 可能内联或溢出记录。当然,任何大于 8KB 的文本/blob 都必须取消记录。

让我们看另一个例子:4 列,每列 3KB,4 个“小”字符串。首先,将允许记录 4 个小字符串。然后,我认为其中两个会被分配到记录中,但最后两个不适合,所以...

  • 对于 COMPACT,前 768 个字节将在记录中,其余将在记录外。
  • 对于 DYNAMIC,没有任何列在记录中。
  • 短于 40 个字节的文本“始终”存储在记录中。

(COMPRESSED 又增加了一条皱纹——压缩块小于 16KB。)

对于需要取消记录的文本/blob,会保留一个 20 字节的“指针”,以便可以找到它。这实际上表示您不能拥有超过 400 (8K/20) 个大文本列(不是下面提到的 1017 个)。

索引存储在单独的 BTree 中。它的行为与数据 BTree 非常相似。但是,由于 3072 限制(索引中的每列),没有“记录外”的概念。 (旁注:即 3072 字节,这是 `VARCHAR(768) CHARACTER SET utf8mb4 需要的。768 是 _characters。)最大密钥长度为 3500 字节。

回到你的第一点...一行的最大大小是(我认为)4GB。 8KB 只是可以保存在它的记录部分中的内容。更多“限制”:http://mysql.rjweb.org/doc.php/limits

有些人打的是“列太多”。 InnoDB 中的限制是 1017,如果所有 1017 都是 BIGINTs,这接近匹配 8KB 的限制。但是对于大 DECIMALs 或中等大小的 VARCHARs,无论行格式如何,您都可以构建少于 1017 列的行,而这些列不适合。

回到你的问题 1。不。你的 4 个文本列中的每一个都可能有很多兆字节。

问题 2 要复杂得多。我在上面回答了一些。

“可用空间”——在 InnoDB BTrees 中有很多无人认领的可用空间。如此之多以至于我有一个经验法则,它说行大小的简单计算(每个 INT 4 个字节等)需要乘以 2 到 3 以容纳所有开销和“空闲”空间。是的,有时会回收一些“可用空间”。但是细节很长而且涉及。

所有这些的最终结果是,大多数表,无论是否包含大列,都表现得相当好。

抱歉,这只是正在发生的事情的简化版本。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。