6

我正在查看 MySQL 中的一个简单表,它有 4 列,大小如下,

unsigned bigint (8 bytes)
unsigned bigint (8 bytes)
unsigned smallint (2 bytes)
unsigned tinyint (1 byte)

所以我希望 19 字节/行。

此表中有 1,654,150 行,因此数据大小应为 31,428,850 字节(或大约 30 兆字节)。

但我可以通过 phpMyAdmin 看到数据占用了 136.3 MiB(不包括索引的大小bigint 1, smallint, tinyint为 79 MiB)。

存储引擎是 InnoDB,主键是bigint 1, bigint 2(用户 ID 和唯一项目 ID)。


编辑:根据评论中的要求,这是一个结果SHOW CREATE TABLE storage

CREATE TABLE `storage` (
 `fbid` bigint(20) unsigned NOT NULL,
 `unique_id` bigint(20) unsigned NOT NULL,
 `collection_id` smallint(5) unsigned NOT NULL,
 `egg_id` tinyint(3) unsigned NOT NULL,
 PRIMARY KEY (`fbid`,`unique_id`),
 KEY `fbid` (`fbid`,`collection_id`,`egg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
4

3 回答 3

2

您的索引在磁盘上有自己的表(尽管您不能直接“看到”它们)。您的数据库的总大小是您的表和索引表的大小。

show create table <tablename>;

您可以看到定义的任何索引。想象一下,将表的总大小和由主键中的两列组成的表相加。添加的那些会让你得到你所看到的大小。

于 2012-07-17T16:28:03.597 回答
2

如果表经常进行插入/删除/更新,您可能想尝试运行OPTIMIZE TABLE查询以查看表可以缩小多少。数据文件中可能存在碎片整理和未使用的空间。

phpmyadmin 向您显示的数据大小不会是您在这里所期望的。你会看到当你第一次创建表时,它不会显示数据使用情况:0。它将是 16KB 或 32KB 之类的。插入记录时大小不会改变。这就是 innoDB 控制表文件的方式,就像它认为的那样高效。

检查SHOW TABLE STATUS FROM {db_name}并查看表中每行的 Avg_row_length 是多少。它也不会是 19 个字节

于 2012-07-17T16:38:37.437 回答
2

磁盘上 InnoDB 的数据大小通常是您计算的 2-3 倍。这是因为

  • 每列的开销(长度,记录的偏移量)
  • 每行开销(tx id 等)
  • 每块开销(16KB)(链接到下一个块——B+Tree)
  • BTree 平均 69% 满
  • MVCC——多版本并发控制。这意味着在事务期间可以同时存在任何行的旧副本和新副本
  • 等等。

一件事会有所帮助:几乎没有应用程序需要BIGINT(8 个字节)的 id。考虑INT UNSIGNED(4 字节,4B 限制)或MEDIUMINT UNSIGNED(3 字节,16M 限制)等。您有 2 个 Bigint,但它们有 4 个副本——辅助键隐含包含 PK 列。

PRIMARY KEY数据一起存储,因此产生的开销非常小。二级键实际上是 4 列,是一个具有类似开销集的 BTree。

即使在 MyISAM 中,也有开销:

  • 每行至少 1 个字节。(在您的情况下为 1)
  • 每 8NULLable列 1 个字节(在您的情况下没有)
  • DELETEd在行是或之后丢失了一些空间UPDATEdFIXED(由于记录大小,在您的情况下更新不会成为问题。)
  • PRIMARY KEY就像任何其他索引一样
  • 所有键都有 69% 的问题;块为 1KB

(既然你没有VARCHARor TEXT,我就不需要讨论 `CHARACTER SET 问题了。)

在 InnoDB 中,行数的估计值SHOW TABLE STATUS通常相差 2 倍。Avg_row_length 计算为 Data_length / Rows,因此它通常是关闭的。

推荐OPTIMIZE TABLEInnoDB 表;这几乎总是不值得付出努力。

这样做时ALTER TABLE .. ADD INDEX ..,旧版本的 MySQL 将重建整个表和索引。这样做,你得到的效果OPTIMIZE。(数据大小增加的可能性不大,但并非不可能。)较新的版本仅添加新索引。你运行的是什么版本?

每个INDEX都是一个单独的 BTree(除了 InnoDB 中的 PK)(除了FULLTEXTand SPATIAL)。

于 2017-03-21T01:16:34.207 回答