MySQL / InnoDB如何在内部表示NULL值?

时间:2017-08-27 20:25:57

标签: mysql innodb

在MySQL中(或者我应该说:使用MySQL的InnoDB引擎) - 如何表示空值?即,如果允许列有NULL s,表(或记录级别的单个记录)的表示如何变化?

如果它对于不同的列数据类型有所不同 - 要么解释表示NULL的各种方法,要么只选择一种数据类型(例如INT)。

2 个答案:

答案 0 :(得分:3)

<强>参考

https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html

引用和解释

ROW_FORMAT=REDUNDANT

  

SQL NULL值在记录目录中保留一个或两个字节。除此之外,如果存储在可变长度列中,则SQL NULL值在记录的数据部分中保留零个字节。在固定长度的列中,它在记录的数据部分中保留列的固定长度。为NULL值保留固定空间可以将列的更新从NULL更新到非NULL值,而不会导致索引页碎片。

也就是说,NULL为1位/ col,没有数据节省。

ROW_FORMAT=COMPACT

  

记录头的可变长度部分包含用于指示NULL列的位向量。如果索引中可以为NULL的列数是N,则位向量占用CEILING(N / 8)个字节。 (例如,如果有9到15列可以为NULL,则位向量使用两个字节。)NULL列不占用此向量中的位以外的空间。标题的可变长度部分还包含可变长度列的长度。每个长度需要一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都是非NULL并且具有固定长度,则记录头没有可变长度部分。

即1位/ col,数据空间为零。

我怀疑,在没有证据的情况下,DYNAMICCOMPRESSED就像COMPACT

列长

每列的前面都有1或2个字节的长度。 1或2的选择基于最大潜在列宽。 (注意:虽然LONGTEXT需要4个字节的长度,但&#39;长度&#39;实际上是在讨论存储在记录中的数量,而不是溢出。)

溢出存储空间

当我谈论这个主题时,这里有一些关于&#34; long&#34; strings / blobs - 无论是在记录中还是存储在别处:

  • &lt; = 40个字节(在给定列中):存储在记录中。
  • 如果整个记录大约适合8KB:存储在记录中。
  • 否则,COMPACT:长列为768 + 20
  • 否则,DYNAMICCOMPRESSED:20列为长列

&#34; 768&#34;表示文本/ blob的前768个字节存储在记录中; &#34; 20&#34;表示一个20字节的指针&#39;到其余(或全部)存储的位置。

KEY_BLOCK_SIZE控制聚簇索引中存储的列数据量,以及溢出页面上的数据量。

(我要离开REDUNDANT,因为我没有详细信息。)

经验法则

每个InnoDB行有20-30个字节的开销。

BTree(包括InnoDB的数据,加上每个二级索引)吸引了69%的满分作为块分割等。

&#34; Data_free&#34;可悲的是不完整;不相信它。

MyISAM非常简陋;很容易计算MyISAM表的空间。从那里,乘以2-3以获得InnoDB所需的空间。 (有例外,通常涉及MyISAM碎片,PK群集等)。

答案 1 :(得分:2)

这仅适用于COMPACT(除非您访问字典表,否则REDUNDANT仅出于历史原因而感兴趣)。 对于每个可以使用NULL的列,NULLS头中有一位。

如果表中没有NULL-able字段,则NULLs标头大小为零。

如果列值为NULL,则设置该位,并且记录数据中没有值。

如果列值不为NULL,则取消设置该位,并将列值存储在记录的数据中。

Record in COMPACT format