如何在MySQL中优化InnoDB表


8

我一直在研究如何仅在MySQL中优化碎片表,并回顾了有关优化表的文章。基本上,它针对任何表对information_schema数据库执行查询,data_free > 0OPTIMIZE仅对那些表构建SQL语句。我运行了此查询,它确定了148个表以进行优化。标识的所有表都是InnoDB表。执行结果优化SQL脚本后,我重新运行原始脚本以识别碎片表,并在第一遍过程中返回完全相同的表。

我看到了有关InnoDB表和OPTIMIZE命令的冲突帖子。有人说这OPTIMIZE不适用于InnoDB表,需要运行ALTER TABLE table_name ENGINE=INNODB。其他人则说,针对InnoDB表执行时OPTIMIZE实际上会调用该ALTER TABLE命令。考虑到这一点,我ALTER TABLE对被标识为碎片(data_free > 0)的InnoDB表之一运行了该命令,发现其data_free之后没有改变。它仍然大于0。我还重新启动了MySQL,并检查了它以发现相同的结果。

现在,我们组织中有几台运行MySQL 5.5.29的服务器,我对所有服务器进行了查询,以识别出任何带有InnoDB表且未DATA_FREE=0 or NULL返回任何表。它们都大于零。

我还OPTIMIZE对一些大于零的MyISAM表运行了该命令,DATA_FREE然后验证它是否为零。

谁能为我阐明一下?从InnoDB表中删除碎片的正确方法是什么?确定零散的InnoDB表的正确方法是什么?

谢谢

Answers:


9

我假设您正在使用innodb_file_per_table此答案。

“ InnoDB碎片化”有多个含义:

  1. .ibd 文件是零散的,非常大,而数据集很小
  2. 索引页面是零散的,因为页面太多而包含很少的数据,在这种情况下可以合并它们。

请考虑一下我之前写的这篇文章:它显示了从大表中清除许多行之后,数据文件是如何碎片化的(即,文件系统中的文件很大-这是一个已知问题,这些文件的大小永远不会减小)。但是,索引并没有在删除结束时就零散:这是因为InnoDB在页面变空时会正确地合并页面。

OPTIMIZE命令确实不适用于InnoDB。它要做的是重建表(就像一样ALTER)。看到这个:

mysql [localhost] {msandbox} (test) > create table t(id int) engine=innodb;

mysql [localhost] {msandbox} (test) > optimize table t;
+--------+----------+----------+-------------------------------------------------------------------+
| Table  | Op       | Msg_type | Msg_text                                                          |
+--------+----------+----------+-------------------------------------------------------------------+
| test.t | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| test.t | optimize | status   | OK                                                                |
+--------+----------+----------+-------------------------------------------------------------------+

至于DATA_FREE:我建议您只是忽略此变量。老实说,我已经使用InnoDB表10多年了,并且从未发现此值与任何东西都非常一致。

现在是时候进行真正的讨论了:您到底想实现什么?除非您的数据库完全陈旧,否则总会有一些碎片。在表中添加,删除和更新行的过程很自然。

碎片并不是那么邪恶:可用新数据来回收可用空间。如果表不是很大,那么就算了整件事。对于非常大的表,您可以通过优化表来获得一些磁盘空间。但是请问自己:表将在多长时间后达到相同的碎片状态?一小时?一天?一周?在所有这些情况下,恕我直言,优化表是没有意义的。

但是,如果大型表中的数据已被大量清除(这预计不会返回),那么我将全力优化它。假设您意识到自己有一些冗余数据,这些数据约占表大小的30%。当然,拥有该磁盘空间会很棒。

底线:只考虑非常大的表的这些问题;仅当磁盘空间有问题时。


我同意data_free没有用。它仅对表空间的“自由扩展区”中的空间进行计数,这是计算碎片的可怕指标。我认为,如果您不使用innodb_file_per_table它,共享表空间中的每个表也会显示相同的值。
jeremycole 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.