为什么我的桌子尺寸比预期的大4倍? (行×字节/行)

时间:2012-07-17 16:21:13

标签: mysql storage innodb

我正在查看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

3 个答案:

答案 0 :(得分:2)

您的索引在磁盘上有自己的表(尽管您无法直接'看到'它们)。 db的总大小是表和索引表的大小。

运行

show create table <tablename>;

您可以看到定义的任何索引。想象一下,添加表的总大小以及包含主键中两列的表。添加的那些,将为您提供您所看到的尺寸。

答案 1 :(得分:2)

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

phpmyadmin显示的数据大小不符合您的预期。您将在第一次创建表时看到,它不会显示数据用法:0。它将是16KB或32KB或其他东西。插入记录时,大小不会改变。这就是innoDB如何控制表文件的效率。

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

答案 2 :(得分:2)

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

  • 每列开销(长度,记录的偏移量)
  • 每行开销(tx id等)
  • 每个块的开销(16KB)(链接到下一个块 - B +树)
  • 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)
  • 每8 NULLable列1个字节(在您的情况下无一个)
  • 行后DELETEdUPDATEd有一些丢失的空间。 (由于记录的FIXED记录大小,更新后的版本无法解决问题。)
  • PRIMARY KEY就像任何其他索引一样
  • 所有密钥都有69%的问题;块是1KB

(由于您没有VARCHARTEXT,我不需要讨论`CHARACTER SET问题。)

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

为InnoDB表推荐OPTIMIZE TABLE;它几乎总是不值得努力。

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

每个INDEX都是一个单独的BTree(InnoDB中的PK除外)(FULLTEXTSPATIAL除外)。