当我执行 SHOW TABLE STATUS databaseName 时;
我在所有表中获得了值为 17825792 的 Data_free 信息:
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
| ubqACL | InnoDB | 10 | Compact | 0 | 0 | 16384 | 0 | 16384 | 17825792 | 1 | 2011-08-23 17:45:48 | NULL | NULL | utf8_general_ci | NULL | | Access Control List per a ubqDocs |
| ubqAssociacions | InnoDB | 10 | Compact | 1216 | 148 | 180224 | 0 | 262144 | 17825792 | 1246 | 2011-08-23 17:45:48 | NULL | NULL | utf8_general_ci | NULL | | Vincles entre documents |
数据库引擎是InnoDB。
我想检索该值来计算碎片并触发优化操作。
答案1
Data_free 在每个表上总是返回相同数字的原因很简单:
- 您未使用表 1. innodb_file_per_table
- 所有 InnoDB 数据都位于名为 /var/lib/mysql/ibdata1 的大文件中。
只要这两个条件成立,你永远无法消除碎片化. 任何针对 InnoDB 表运行 OPTIMIZE TABLE 的尝试都会使表的数据和索引连续,但会附加到 ibdata1,从而使 ibdata1 变得更大。
鉴于此,您必须知道 ibdata1 里面有什么。里面有四 (4) 种类型的信息:
- 表格数据页
- 表索引页
- 表元数据
- 脉动循环控制电路数据
你必须做四(4)件大事:
- 转储所有数据库
- 删除 ibdata1
- 使用 innodb_file_per_table 重新配置 InnoDB
- 重新加载转储
这会将所有数据和索引保留在 ibdata1 之外,并将它们存储在单独的 .ibd 文件中。从那里,您可以针对配置为 innodb_file_per_table 的 InnoDB 表运行 OPTIMIZE TABLE。因此,.ibd 文件可以单独进行碎片整理。
- 我最初于 2010 年 10 月 29 日在 StackOverflow 上撰写了这篇文章
- 我也在 2011 年 2 月 4 日的 ServerFault 上写过这篇文章
- 2011 年 3 月 11 日,ServerFault
这将使 ibdata1 尽可能小,永远不会再疯狂增长而失控。所有关于 InnoDB 碎片整理的担忧都只需一个 OPTIMIZE TABLE 即可解决。
-- 需要注意的是,INNODB 表上的 OPTIMIZE TABLE 操作与使用其他存储引擎略有不同。Percona 有一篇关于提高 OPTIMIZE TABLE 速度的好文章,以及何时应该/不应该考虑执行该操作这里。
“对于 InnoDB 表,OPTIMIZE TABLE 映射到 ALTER TABLE,后者重建表以更新索引统计信息并释放聚集索引中未使用的空间。”