Answers:
在Innodb物理行结构中,REDUNDANT ROW_FORMAT下的项目符号#7
SQL NULL值在记录目录中保留一个或两个字节。除此之外,如果将SQL NULL值存储在可变长度column中,则在记录的数据部分中保留零字节。在固定长度的列中,它在记录的数据部分中保留列的固定长度。保留NULL值的固定空间可以将列从NULL更新为非NULL值,而不会引起索引页的碎片。
在Innodb物理行结构中,COMPACT ROW_FORMAT下的项目符号#2
记录头的可变长度部分包含一个用于指示NULL列的位向量。如果索引中可以为NULL的列数为N,则位向量占用CEILING(N / 8)个字节。(例如,如果有9到15列可以为NULL的列,则位向量使用两个字节。) NULL列不占用此vector中的位以外的空间。标头的可变长度部分还包含可变长度列的长度。每个长度占用一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都不为空并且具有固定长度,那么记录头将没有可变长度部分。
根据这些要点,这是NULL
列的存储占用的值
现在,由于要指出的第一点,您必须在使用CHAR和VARCHAR之间做出选择
保留NULL值的固定空间可以将列从NULL更新为非NULL值,而不会导致索引页碎片
一旦存储了非NULL数据,这将防止引入行的任何碎片。这是我之前讨论过的有关MyISAM的问题:请参阅我的旧文章。在固定大小的字段上使用CHAR vs VARCHAR会对性能产生什么影响?。
SELECT
需要创建临时表的组合系统时,就会出现过度分配的问题。如果可能的话,它将使用MEMORY
,并转换VARCHAR
到CHAR
对TMP表。现在VARCHAR(100)
占用固定的100(或300)字节,从而可能减慢查询速度。
无论您为varchar列定义的长度如何,一个空列使用的存储空间都将相同。
这仅解决varchar列使用的空间,而不考虑该行,其索引,主键和其他列使用的总存储空间。
正如ypercube在他的评论中提到的那样,当存在至少一个可空列时,整个行还需要考虑其他事项。
记录头的可变长度部分包含一个用于指示NULL列的位向量。如果9到15列之间的任何地方都可以为NULL,则位向量使用两个字节。)
...
标头的可变长度部分还包含可变长度列的长度。每个长度占用一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都不为空并且具有固定长度,那么记录头没有可变长度部分
是的,使用的存储空间会根据您选择的类型(固定的还是可变的),排序规则和其他因素(例如引擎)而变化。
MySQL在此处提出有关优化数据存储的建议:优化数据大小
更新资料
使用varchar的另一项考虑是内存。在MySQL中,尽可能限制可变长度列的大小很重要。即使该列是可变的并且使用的存储空间是可变的,MySQL也会以固定块的形式分配内存来存储值。例如,varchar(200)将使用比varchar(5)更多的内存。这不是存储空间问题,但在定义列时仍要考虑一些问题。
CHARACTER SET
latin1或ascii。对于UTF8,存储要求CHAR(4)
是12