InnoDB + innodb_file_per_table:可配置的扩展区大小,以避免浪费磁盘空间?

时间:2014-01-20 09:39:48

标签: mysql innodb mariadb

我一直在尝试使用MariaDB(Win32 / 5.5.34-MariaDB-31.1),尝试将其用作实时归档应用程序的数据库服务器。我使用innodb_file_per_table=1,因此每个表都是一个单独的.ibd文件。当旧数据被删除时,这对OPTIMIZE TABLE等维护非常方便。

我有一个小型测试应用程序,包含大约2,600个表(每个存档对象使用一个表)。在磁盘上,这些表消耗大约12 GB,有用的数据(data_length + index_length)大约是4 GB(到目前为止,我只是插入/更新行,没有删除)。添加data_length + index_length + data_free时,我会看到9 GB。

主要问题似乎是个人.ibd文件的增长方式。我已经执行了2次测试(在COMPACTCOMPRESSED表上)。首先它们增长几KB,但随后它们的大小会增加。例如:163 kB,180 kB,229 kB ... 589 kB,606 kB然后跳转到2 MB,再到9 MB。

这一观察结果与the documentation同意:

  

此变量不会影响每个表的表空间文件   如果您使用innodb_file_per_table=1,则会创建。那些文件是   无论innodb_autoextend_increment的值如何,都会自动扩展。   初始扩展是少量的,之后是扩展   以4 MB的增量发生。

所以似乎每个表(超过某个限制)都有0-4 MB未使用但分配空间(假设平均为2 MB)。我无法在文档中找到任何可以建议可以配置此范围大小的内容。这就是我的问题:

可以在MySQL / MariaDB / MySQL的其他替代品上更改此自动扩展大小吗?每个表当前2 MB是一个不可接受的高开销(生产系统可能有100,000个表或更多,即200 GB浪费的空间)。

当我们使用Oracle时,它没有'one_file_per_table'选项,但是为了避免数据文件碎片(由删除旧数据然后整理alter table shrink space引起),使用{{1}创建表空间告诉Oracle使用固定大小的范围而不是默认的增长范围大小。 (默认增长范围导致固定大小的表空间具有超过10 GB的可用空间,但由于没有足够大的连续块可用而无法扩展表。删除旧数据后回收所有10 GB这是一个很小的范围。)

2 个答案:

答案 0 :(得分:1)

有一些事情可以使用一些澄清。 InnoDB表被组织成1 MB范围,其中未压缩表的默认页面大小为64页。允许innodb_file_per_table = 1的非常小的表小于一个范围,主要是对具有许多非常小的表的人进行优化。但是,当表格增长超过几页时,它会开始增加分配大小,以避免开销并最大限度地减少表的碎片,正如您所注意到的那样。对于像你这样的用例改进这种策略并没有太多的考虑,主要是因为你的用例是一个数据库反模式。

所以,真正的答案是你应该重新考虑你的数据库设计。

但是,使用您当前的数据库设计,您可能会更好地使用innodb_file_per_table = 0。在这种情况下,所有表将最终放在一个名为ibdata1的文件中(如果您手动配置表空间大小,则为几个文件),并且必要时会增长。如果您删除数据或重建表格,例如OPTIMIZE TABLEibdata1中提供的空间将根据需要有效地重用于其他表。目前没有办法缩小InnoDB(.ibdibdataX)中的任何表空间文件,因此不幸的是,您将无法将磁盘空间恢复到操作系统。但是,您可以“返回”并且可以在InnoDB中重复使用它,因此您不必担心它会无限增长。

答案 1 :(得分:0)

我推荐这种技术作为妥协:

  • 将较大的表放在file_per_table中。
  • 将较小的表放在ibdata1中。

粗略猜测,您可以使用80-20 rule表示可能有20%的表占用80%的空间。那些应该是file_per_table。但是YMMV。 (并且,考虑到杰里米的评论。)

如果当前所有内容都在ibdata1中,则必须转储,删除ibdata1并重新加载。一场昂贵的混乱。

如果目前所有内容都在.ibds:

  • 设置全局innodb_file_per_table = ON
  • 退出
  • 重新登录(以获取设置)
  • 重复:ALTER TABLE tbl... ENGINE=InnoDB; - 从.ibd复制到ibdata1并删除.ibd。
  • 完成后,请记住新表将以ibdata1或.ibd格式显示,具体取决于您离开设置的位置。

未来版本可能允许将表分配给“表空间”,而不仅仅是1 / table vs ibdata1的极值。这将开启新的优化技术。我在想:每个数据库有1个表空间,还有自己.ibd中的大表。同时,ibdata1中没有表格。 (当然,如果您的2600个表位于单个数据库中,则无效。)

另一个注意事项:PARTITIONed表格特别浪费,因为它们在每个分区中都有“空闲”空间。 “原生分区”应该改进这一点。 (但我还没有任何指标。)