Documentation Home

13.7.2.4 优化表语句

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

OPTIMIZE TABLE重组表数据和关联索引数据的物理存储,减少存储空间,提高访问表时的I/O效率。对每个表所做的确切更改取决于该 表使用的存储引擎

在这些情况下使用OPTIMIZE TABLE,具体取决于表的类型:

  • InnoDB在对具有自己的 .ibd 文件 的表执行大量插入、更新或删除操作之后,因为它是在 innodb_file_per_table 启用选项的情况下创建的。重组了表和索引,可以回收磁盘空间供操作系统使用。

  • FULLTEXT 在对作为表中索引 一部分的列执行大量插入、更新或删除操作之后InnoDB。首先设置配置选项 innodb_optimize_fulltext_only=1 。要将索引维护周期保持在合理的时间,请设置 innodb_ft_num_word_optimize 选项以指定要在搜索索引中更新多少个单词,并运行一系列OPTIMIZE TABLE语句,直到搜索索引完全更新。

  • MyISAM 在删除or表 的大部分,或对具有可变长度行(具有 、 、 或 列的表)的or表ARCHIVE进行多次更改后。删除的行在链表中维护,后续 操作重用旧行位置。您可以使用它来回收未使用的空间并对数据文件进行碎片整理。在对表进行大量更改后,此语句还可以提高使用该表的语句的性能,有时效果会很显着。 MyISAMARCHIVE VARCHARVARBINARYBLOBTEXTINSERTOPTIMIZE TABLE

此语句需要表SELECTINSERT权限。

OPTIMIZE TABLE适用于 InnoDBMyISAMARCHIVE表格。 OPTIMIZE TABLE也支持内存 NDB表的动态列。它不适用于内存表的固定宽度列,也不适用于磁盘数据表。OPTIMIZE 可以使用 调整 NDB Cluster 表 的性能--ndb-optimization-delay,它控制处理批处理行之间等待的时间长度OPTIMIZE TABLE。有关更多信息,请参阅 第 18.2.7.11 节,“NDB Cluster 7.3 中已解决的先前 NDB Cluster 问题”

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

默认情况下,OPTIMIZE TABLE不适 用于使用任何其他存储引擎创建的表,返回表明缺乏支持的结果。您可以通过使用该 选项启动mysqldOPTIMIZE TABLE来为其他存储引擎工作 。在这种情况下, 只是映射到 . --skip-newOPTIMIZE TABLEALTER TABLE

此语句不适用于视图。

OPTIMIZE TABLE分区表支持。有关将此语句用于分区表和表分区的信息,请参阅 第 19.3.4 节,“分区维护”

默认情况下,服务器将OPTIMIZE TABLE语句写入二进制日志,以便它们复制到副本。要禁止记录日志,请指定可选 NO_WRITE_TO_BINLOG关键字或其别名 LOCAL

仅在 MySQL 5.6.11 中,gtid_next 必须AUTOMATIC在发出此语句之前设置为。(错误#16062608、错误#16715809、错误#69045)

优化表输出

OPTIMIZE TABLE返回一个结果集,其列如下表所示。

柱子 价值
Table 表名
Op 总是optimize
Msg_type status, error, info,notewarning
Msg_text 信息性消息

OPTIMIZE TABLEtable 捕获并抛出将表统计信息从旧文件复制到新创建的文件时发生的任何错误。例如。如果 、 或文件所有者的 .frm用户.MYDID .MYImysqld进程的用户 ID 不同, OPTIMIZE TABLE则会生成“无法更改文件的所有权”错误,除非 mysqldroot用户启动。

InnoDB 详细信息

对于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                                                                |
+----------+----------+----------+-------------------------------------------------------------------+

Mysql 5.6.17之前,OPTIMIZE TABLE不使用 在线DDL。因此,并发 DML ( INSERT, UPDATE, DELETE) 在运行时不允许在表OPTIMIZE TABLE上使用,并且二级索引的创建效率不高。

从 MySQL 5.6.17 开始,对常规表和分区 表OPTIMIZE TABLE使用在线 DDLInnoDB,这减少了并发 DML 操作的停机时间。触发的表重建 OPTIMIZE TABLE就地完成。独占表锁仅在操作的准备阶段和提交阶段短暂使用。在准备阶段,更新元数据并创建中间表。在提交阶段,提交表元数据更改。

OPTIMIZE TABLE在以下条件下使用表复制方法重建表:

OPTIMIZE TABLE包含 索引的表不支持使用 联机 DDL 。改为使用表复制方法。 InnoDBFULLTEXT

InnoDB使用页面分配方法存储数据,并且不会像传统存储引擎(例如 MyISAM)那样受到碎片的影响。在考虑是否运行优化时,请考虑您的服务器预期处理的事务工作量:

MyISAM 详细信息

对于MyISAM表格, OPTIMIZE TABLE其工作方式如下:

  1. 如果表有删除或拆分行,修复表。

  2. 如果索引页未排序,请对它们进行排序。

  3. 如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),请更新它们。

其他注意事项

对于InnoDB5.6.17 之前的表和其他表类型,MySQL在运行期间锁定表OPTIMIZE TABLE。从 MySQL 5.6.17 开始, OPTIMIZE TABLE对常规表和分区InnoDB 表在线执行。

OPTIMIZE TABLE不对 R 树索引进行排序,例如 POINT列上的空间索引。(漏洞 #23578)