2012-08-17 64 views
0

我做了一个测试,以确保我知道ENUM是如何工作的以及它如何处理存储空间......并获得了与预期不同的结果。MySql - 为什么ENUM需要比预期多的空间?

一个表格,其中一个字段的类型为VARCHAR(100),填充1,000,000行。每行有一个值是从6个字符串中的1个随机选择的,长度为100.

然后,转换为ENUM,然后回到VARCHAR(100)。这里是结果(数据大小)。

1行百万= 99.2 MIB,VARCHAR(100)

2.行百万= 6,835.9 KIB,枚举 ( 'blah100Characters1', 'blah100Characters2',..., 'blah100Characters6')

3.行百万99.2 MIB,VARCHAR(100)

VARCHAR(100)类型如预期和MySQL说明书手册中匹配报道的( “L + 1个字节,0 < = L < = 255”) 百万×100 =亿= 99.2 MIB

---编辑:好,加上一个额外的字节,但是这是不相关的讨论: o)

然而,根据ENUM的MySQL规范(“1或2字节,取决于枚举值的数量(最大值为65,535)”),有6种可能的组合,我希望有一个数据每行需要1个字节。 1,000,000 x 1 = 1,000,000 = 976.5 KiB

任何人都可以向我解释为什么转换后的表格需要6,835.9 KiB,奇怪的是,这几乎是预期的7倍多?

+0

看起来像一些数据填充正在应用,虽然金额不是2次轮;-) – 2012-08-17 03:46:59

+0

您正在使用哪种存储引擎?你如何计算大小? – Matthew 2012-08-17 03:48:07

+0

存储引擎是MyISAM,我将按照phpMyAdmin中该表的“Structure”区域底部的“Space Usage”表中报告的内容进行操作。 – Rickaroo 2012-08-17 03:50:48

回答

0

它增加了7个字节(我得到相同的结果);一些空间是填充,一些是用于删除标记。

为了证明有填充,添加额外的枚举(或微小的整数)。表格的大小不会改变。

要证明存在删除标记,请删除中间的一行。表格的大小不会改变。

根据this page,它与myisam_data_pointer_size的默认值为6个字节(加上1个字节的删除)有关。

而且他似乎是正确的,因为如果我这样做:

alter table foo MAX_ROWS=10; 

表的尺寸减小。

此外,从this "bug" report,它听起来像删除的记录存储为指向下一个记录的指针。如果是这样,这意味着任何行的最小空间将是指针大小(默认情况下为6个字节)加上一个删除字节。这是因为如果记录被删除,删除字节被设置,然后其他6个字节被用来指向下一个记录。

如果你想了解更多信息,我可以阅读MyISAM表格的“删除链接链”(当使用固定记录数时)。

+0

嘿,我想你已经知道了。我发现这[链接在mysql手册](http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_myisam_data_pointer_size),默认是6个字节,其中加1我的数据的实际参考字节是7. – Rickaroo 2012-08-17 04:21:59

+0

@Rickaroo,我敢肯定附加字节是删除标志。每条记录都有一个隐藏的删除标志。您的枚举的字节是为可能的行指针保留的那6个字节的一部分。 (如果删除标志是0,那么它知道这6个字节属于你的数据。)我相信这只适用于具有固定长度的记录。即您的varchar版本不是固定长度的,所以它不会得到相同类型的删除+指针处理。 – Matthew 2012-08-17 04:24:00

+0

我想我开始明白了。而当我没有指定我的表将是一个较短的最大长度,它只是分配6个字节,知道该表可能会变得很大并且需要它们进行行索引?我学到的一件事是,虽然我假设VARCHAR没有添加值,但实际上一个VARCHAR(100)单个字段的行长度为104.所以我的错误是假定没有填充VARCHAR。谢谢! – Rickaroo 2012-08-17 04:49:33

相关问题