Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


15.7.3.4 优化表语句

OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name [, tbl_name] ...

OPTIMIZE TABLE 语句重组了表数据的物理存储以及相关索引数据,以减少存储空间并提高当访问表时的I/O效率。对每个表执行的确切更改取决于该表所使用的存储引擎

在以下情况下使用 OPTIMIZE TABLE,取决于表的类型:

  • 在对一个具有自己的.ibd文件innodb_file_per_table选项启用的 InnoDB 表执行了大量插入、更新或删除操作。表和索引被重组,磁盘空间可以回收给操作系统使用。

  • 在对innodb_optimize_fulltext_only=1配置选项设置后,对一个包含在FULLTEXT索引中的innodb_ft_num_word_optimize选项指定的单词数量进行了大量插入、更新或删除操作的 InnoDB 表。为了保持索引维护期间的时间合理,运行一系列OPTIMIZE TABLE语句直到搜索索引完全更新。

  • 在删除大量 MyISAMARCHIVE 表的记录,或者对具有变长行(包含VARCHARVARBINARYBLOBTEXT 列的)的MyISAMARCHIVE 表执行了大量插入、更新或删除操作。删除的记录被保持在一个链表中,随后的INSERT 操作重用旧的行位置。可以使用 OPTIMIZE TABLE 语句回收未使用的空间并对数据文件进行碎片整理。在对表执行了大量更改后,这个语句可能会显著提高访问该表的性能。

这个语句需要SELECTINSERT 权限来访问表。

OPTIMIZE TABLE 语句支持InnoDBMyISAMARCHIVE 表。OPTIMIZE TABLE 语句也支持NDB 表的动态列。它不适用于固定宽度列的内存表,也不适用于磁盘数据表。对OPTIMIZE 语句在 NDB 集群表上的性能可以通过 --ndb-optimization-delay 控制,控制OPTIMIZE TABLE 之间的等待时间。更多信息,请参阅 Section 25.2.7.11, “Previous NDB Cluster Issues Resolved in NDB Cluster 8.4”

对于 NDB 集群表,OPTIMIZE TABLE 可以在执行 OPTIMIZE 操作的 SQL 线程被中断(例如,通过杀死执行 OPTIMIZE 操作的 SQL 线程)。

默认情况下,OPTIMIZE TABLE 不支持使用其他存储引擎创建的表格,并返回一个结果指示这一缺乏支持。您可以通过在启动mysqld时使用--skip-new选项,使OPTIMIZE TABLE支持其他存储引擎。在这种情况下,OPTIMIZE TABLE 将被映射到ALTER TABLE

这个语句不支持视图。

OPTIMIZE TABLE 支持分区表。有关使用该语句与分区表和表格分区的信息,请参阅第26.3.4节,“分区维护”

默认情况下,服务器将OPTIMIZE TABLE 语句写入二进制日志,以便复制到副本。要抑制日志记录,请指定可选的NO_WRITE_TO_BINLOG 关键字或其别名LOCAL。您必须拥有OPTIMIZE_LOCAL_TABLE 权限才能使用此选项。

OPTIMIZE TABLE 返回一个结果集,其列显示在以下表格中。

Column Value
Table 表名
Op 始终为 optimize
Msg_type 状态、错误、信息、注意或警告
Msg_text 信息性消息

OPTIMIZE TABLE 表格捕获并抛出在从旧文件复制表格统计信息到新创建的文件期间发生的任何错误。例如,如果用户 ID 与mysqld 进程的用户 ID 不同,OPTIMIZE TABLE 生成一个“无法更改文件所有权”的错误,除非mysqldroot 用户启动。

对于InnoDB 表格,OPTIMIZE TABLE 被映射到ALTER TABLE ... FORCE,该语句重建表格以更新索引统计信息并释放未使用的空间。这个过程在OPTIMIZE TABLE 的输出中显示,当您对一个InnoDB 表格运行该语句时,如下所示:

mysql> OPTIMIZE TABLE foo;
+----------+----------+----------+-------------------------------------------------------------------+
| Table    | Op       | Msg_type | Msg_text                                                          |
+----------+----------+----------+-------------------------------------------------------------------+
| test.foo | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| test.foo | optimize | status   | OK                                                                |
+----------+----------+----------+-------------------------------------------------------------------+

OPTIMIZE TABLE 使用在线DML对普通和分区的InnoDB表进行优化,减少了并发DML操作的停机时间。表重建由OPTIMIZE TABLE触发,在执行过程中只会短暂地获取一个排他性表锁。在准备阶段,元数据被更新,并创建一个临时表。在提交阶段,表的元数据更改被提交。

OPTIMIZE TABLE 使用在线DML在以下条件下重建表:

OPTIMIZE TABLE 使用在线DML不支持包含FULLTEXT索引的InnoDB表。相反,使用了表复制方法。

InnoDB 使用页面分配方式存储数据,不像遗留存储引擎(如MyISAM)那样会出现碎片。当考虑是否运行优化时,考虑服务器预期处理的交易工作负载:

  • 某种程度的碎片是可接受的。InnoDB 只填充页面到93%满,以留出空间更新数据而不需要分割页面。

  • 删除操作可能会留下空洞,使得页面比理想状态更为空,这可能值得优化表格。

  • 更新行通常在同一页面内重写数据,除非有足够的空间可用,否则依赖于数据类型和行格式。请参阅第17.9.1.5节,“InnoDB表的压缩工作原理”第17.10节,“InnoDB行格式”

  • 高并发工作负载可能会随着时间的推移在索引中留下空洞,因为InnoDB 通过其MVCC机制保留多个版本相同数据的不同版本。请参阅第17.3节,“InnoDB多版本控制”

对于MyISAM表,OPTIMIZE TABLE 如下工作:

  1. 如果表中有删除或分割的行,修复表。

  2. 如果索引页面未排序,排序它们。

  3. 如果表的统计信息不更新(并且无法通过排序索引来修复),则更新它们。

OPTIMIZE TABLE 对于普通和分区的InnoDB表进行在线优化。否则,MySQL在运行OPTIMIZE TABLE时锁定表。

OPTIMIZE TABLE 不会对R-树索引进行排序,如POINT列上的空间索引。(问题#23578)