Mysql InnoDB+;innodb_file_per_表:可配置的扩展数据块大小以避免浪费磁盘空间?

Mysql InnoDB+;innodb_file_per_表:可配置的扩展数据块大小以避免浪费磁盘空间?,mysql,innodb,mariadb,Mysql,Innodb,Mariadb,我一直在试验MariaDB(Win32/5.5.34-MariaDB-31.1),试图将其用作实时存档应用程序的DB服务器。我使用innodb\u file\u per\u table=1,因此每个表都是一个独立的.ibd文件。这便于维护,例如删除旧数据时的优化表 我有一个小的测试应用程序,有2600个表(每个归档对象使用一个表)。在磁盘上,这些表消耗约12GB的有用数据(data\u length+index\u length)约为4GB(到目前为止,我只插入/更新行,没有删除)。当添加dat

我一直在试验MariaDB(Win32/5.5.34-MariaDB-31.1),试图将其用作实时存档应用程序的DB服务器。我使用
innodb\u file\u per\u table=1
,因此每个表都是一个独立的
.ibd
文件。这便于维护,例如删除旧数据时的
优化表

我有一个小的测试应用程序,有2600个表(每个归档对象使用一个表)。在磁盘上,这些表消耗约12GB的有用数据(
data\u length
+
index\u length
)约为4GB(到目前为止,我只插入/更新行,没有删除)。当添加
data\u length
+
index\u length
+
data\u free
时,我看到了9 GB

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

这一观察结果与以下结论一致:

此变量不影响每个表的表空间文件 如果使用
innodb\u file\u per\u table=1
创建。那些文件是 自动扩展,不考虑innodb\u autoextend\u increment的值。 最初的扩展是少量的,之后扩展 以4MB的增量出现

因此,似乎每个表(增长超过某个限制)都有0-4MB未使用但已分配的空间(平均为2MB)。我在文档中找不到任何建议可以配置此扩展数据块大小的内容。这就是我的问题:

可以在MySQL/MariaDB/MySQL的其他替代方案上更改此自动扩展大小吗?当前每个表2 MB的开销高得令人无法接受(生产系统可能有100000个或更多表,即200 GB的浪费空间)

当我们使用Oracle时,它没有“每个表一个文件”选项,而是为了避免数据文件的碎片(由于删除旧数据,然后通过
alter table shrink space
进行整理而导致)表空间是使用
space EXTENT MANAGEMENT LOCAL UNIFORM SIZE 128 K
创建的,它告诉Oracle使用固定大小的扩展数据块,而不是默认的扩展数据块大小。
(当固定大小的表空间有超过10 GB的可用空间,但由于没有足够大的连续块可用,表无法扩展时,默认的增长范围会导致这种情况。删除小范围中的旧数据后,所有10 GB都会被回收).

有几件事需要澄清。InnoDB表被组织成1 MB的数据块,未压缩表的默认页面大小为64页。允许
innodb_file_per_table=1
的非常小的表小于一个区段,主要是为了对拥有许多非常小的表的人进行优化。然而,正如您所注意到的,当表增长到超过几页时,它开始增加分配大小,以避免开销并最小化表的碎片。对于像您这样的用例,没有太多的考虑来改进这种策略,主要是因为您的用例有点像数据库反模式

因此,真正的答案是您应该重新考虑您的数据库设计


但是,在当前的数据库设计中,使用
innodb\u file\u per\u table=0可能会更幸运。在这种情况下,所有的表都会在一个名为
ibdata1
的文件中结束(如果手动配置表空间大小,则会有几个文件),并且会根据需要增加。如果使用例如
优化表
删除数据或重建表,则
ibdata1
中可用的空间将根据需要有效地重新用于其他表。InnoDB(
.ibd
ibdataX
)中目前没有收缩任何表空间文件的方法,因此很遗憾,您将无法将磁盘空间恢复到操作系统。但是,您可以将其“取回”,并且可以在InnoDB中重复使用,因此您不必担心它会无限期地增长。

我建议将此技术作为一种折衷方法:

  • 将较大的表放在每个表的文件中
  • 将较小的表放在ibdata1中
粗略地猜测,您可以使用表示可能有20%的表占用了80%的空间的。所以这些应该是每个表的文件。但是YMMV。(并且,考虑杰里米的评论。)

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

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

  • 将全局
    innodb\u文件\u per\u table=设置为ON
  • 注销
  • 重新登录(以获取设置)
  • 重复:
    更改表tbl。。。引擎=InnoDB--从.ibd复制到ibdata1并删除.ibd
  • 完成后,请记住新表将放入ibdata1或.ibd中,具体取决于您离开设置的位置
未来的版本可能允许将表分配给“表空间”,而不仅仅是1/table与ibdata1的极端值。这将开启新的优化技术。我的想法是:每个数据库1个表空间,再加上大表仍然在自己的.ibd中。同时,ibdata1中没有表。(当然,如果您的2600个表位于一个数据库中,则这没有帮助。)


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

2600个表?每件物品一张桌子?也许你应该重新考虑你的数据库设计。您好,是的,每个对象一个表。我将不详细介绍,但有“简单的存档”-例如,想象一下存档由传感器测量的温度(此表有DATETIME列,DOUBLE列)