InnoDB 字段类型大小与文件大小差异?
InnoDB field type size vs file size descrepency?
我创建了这些表:
create table aca (money TINYINT);
create table acb (money SMALLINT);
create table acc (money INT);
create table acd (money BIGINT);
我运行以下反复插入添加9420行:
INSERT INTO aca (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acb (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acc (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acd (money) VALUES(7), (8), (9), (10), (12);
当我检查服务器上的文件时,它显示每个数据库都比另一个稍大:
-rw-r----- 1 mysql mysql 360448 Jul 5 14:21 aca.ibd
-rw-r----- 1 mysql mysql 376832 Jul 5 14:21 acb.ibd
-rw-r----- 1 mysql mysql 393216 Jul 5 14:21 acc.ibd
-rw-r----- 1 mysql mysql 442368 Jul 5 14:21 acd.ibd
由于每个字段的大小都是下一个字段的两倍,我希望每个数据库文件的大小大约是其两倍(由于 headers 存在细微差别),但事实并非如此,而是尺寸是原来的两倍(大 100%),它们大 4-13%。
为什么?
什么进入 InnoDB table?这是一个粗略的列表:
- 因为你还没有
PRIMARY KEY
,所以添加了一个隐藏的6字节数字。
- 每列前面都有一个长度和空信息。在您的情况下,这可能每行增加 2 个字节。
- 每一行都有各种开销,包括事务处理等。估计每行 29 个字节。
- 一个 BTree 被填充到不超过 15/16 满。 (15KB / 16KB).
同时,对于典型的 table 定义,一个方便的经验法则是将明显的总列大小乘以 2 到 3 之间以获得 .ibd 文件的大小。这不适用于您的情况,因为您的列数 (1) 少得不切实际。
仅查看基本的常量开销:
9420 * 16/15 * (29+6) = 351KB
这个数字非常适合作为您获得的 table 尺寸的下限。
另一个问题:在某些时候,InnoDB 抓取了 4/8/16MB 的 space ("extents") 块(我不确定它的大小)。我想你还没有击中那个。发生这种情况时,计算会变得更加混乱和难以理解。
可以这么说,InnoDB 做了一些权衡。他们 'waste' 一些 space(有时很多 space)使处理更简单和更快。
如果你有一个 PRIMARY KEY
那么 15/16 就有问题了。如果您按 PK 顺序插入,则 15/16 棒。但如果你随机插入,它会下降到 69% 左右。这是因为块分裂。
哦,"large" text/blob 列变为 "off-record"。 ROW_FORMAT
增加了皱纹。
而且,如果你用 MyISAM 这样做,你会得到令人费解的大小,如 75360、75360、75360 和 94200。这些更容易解释,而且,如果我没弄错的话,非常预测table.
够糊涂了吗?
我创建了这些表:
create table aca (money TINYINT);
create table acb (money SMALLINT);
create table acc (money INT);
create table acd (money BIGINT);
我运行以下反复插入添加9420行:
INSERT INTO aca (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acb (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acc (money) VALUES(7), (8), (9), (10), (12);
INSERT INTO acd (money) VALUES(7), (8), (9), (10), (12);
当我检查服务器上的文件时,它显示每个数据库都比另一个稍大:
-rw-r----- 1 mysql mysql 360448 Jul 5 14:21 aca.ibd
-rw-r----- 1 mysql mysql 376832 Jul 5 14:21 acb.ibd
-rw-r----- 1 mysql mysql 393216 Jul 5 14:21 acc.ibd
-rw-r----- 1 mysql mysql 442368 Jul 5 14:21 acd.ibd
由于每个字段的大小都是下一个字段的两倍,我希望每个数据库文件的大小大约是其两倍(由于 headers 存在细微差别),但事实并非如此,而是尺寸是原来的两倍(大 100%),它们大 4-13%。
为什么?
什么进入 InnoDB table?这是一个粗略的列表:
- 因为你还没有
PRIMARY KEY
,所以添加了一个隐藏的6字节数字。 - 每列前面都有一个长度和空信息。在您的情况下,这可能每行增加 2 个字节。
- 每一行都有各种开销,包括事务处理等。估计每行 29 个字节。
- 一个 BTree 被填充到不超过 15/16 满。 (15KB / 16KB).
同时,对于典型的 table 定义,一个方便的经验法则是将明显的总列大小乘以 2 到 3 之间以获得 .ibd 文件的大小。这不适用于您的情况,因为您的列数 (1) 少得不切实际。
仅查看基本的常量开销:
9420 * 16/15 * (29+6) = 351KB
这个数字非常适合作为您获得的 table 尺寸的下限。
另一个问题:在某些时候,InnoDB 抓取了 4/8/16MB 的 space ("extents") 块(我不确定它的大小)。我想你还没有击中那个。发生这种情况时,计算会变得更加混乱和难以理解。
可以这么说,InnoDB 做了一些权衡。他们 'waste' 一些 space(有时很多 space)使处理更简单和更快。
如果你有一个 PRIMARY KEY
那么 15/16 就有问题了。如果您按 PK 顺序插入,则 15/16 棒。但如果你随机插入,它会下降到 69% 左右。这是因为块分裂。
哦,"large" text/blob 列变为 "off-record"。 ROW_FORMAT
增加了皱纹。
而且,如果你用 MyISAM 这样做,你会得到令人费解的大小,如 75360、75360、75360 和 94200。这些更容易解释,而且,如果我没弄错的话,非常预测table.
够糊涂了吗?