OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL]
TABLE tbl_name [, tbl_name] ...
OPTIMIZE TABLE 重新组织表数据和相关索引数据的物理存储,以减少存储空间,提高访问表时的 I/O 效率。对每个表所做的确切更改取决于该表使用的存储引擎。在这些情况下,根据表的类型使用 OPTIMIZE TABLE:● 在启用 innodb_file_per_table 选项的情况下创建的 InnoDB 表具有自己的 .ibd 文件,对表执行大量插入、更新或删除操作后,表和索引被重新组织,磁盘空间可以被回收以供操作系统使用。● 对 InnoDB 表中作为 FULLTEXT 索引组成部分的列执行大量插入、更新或删除操作之后。首先设置配置选项 innodb_optimize_fulltext_only=1。要使索引维护周期保持在合理的时间内,请设置 innodb_ft_num_word_optimize 选项以指定搜索索引中要更新的单词数,并运行一系列 OPTIMIZE TABLE 语句,直到搜索索引完全更新。● 在删除 MyISAM 或 ARCHIVE 表的大部分内容,或对包含变长行(包含 VARCHAR、VARBINARY、BLOB 或 TEXT 列的表)的 MyISAM 或 ARCHIVE 表进行许多更改之后。删除的行保存在一个链表中,后续的 INSERT 操作将重用旧的行位置。可以使用 OPTIMIZE TABLE 来回收未使用的空间并整理数据文件。在对表进行大量更改之后,这条语句还可以提高使用该表的语句的性能,有时会显著提高。此语句需要表的 SELECT 和 INSERT 权限。OPTIMIZE TABLE 语句适用于 InnoDB、MyISAM 和 ARCHIVE 表。内存中 NDB 表的动态列也支持 OPTIMIZE TABLE。它不适用于内存表的固定宽度列,也不适用于磁盘数据表。可以使用 --ndb-optimization-delay 来优化 NDB Cluster 表上的 OPTIMIZE 性能,它通过 OPTIMIZE TABLE 控制处理批处理行之间的等待时间长度。对于 NDB Cluster 表,可以通过(例如)终止执行优化操作的 SQL 线程来中断 OPTIMIZE TABLE。默认情况下,OPTIMIZE TABLE 不适用于使用其他存储引擎创建的表,会返回结果,表明不支持该操作。通过使用 --skip-new 选项启动 mysqld,可以使 OPTIMIZE TABLE 对其他存储引擎起作用。在这种情况下,OPTIMIZE TABLE 只是映射到 ALTER TABLE。默认情况下,服务器将 OPTIMIZE TABLE 语句写入二进制日志,以便它们复制到副本。要禁止日志记录,请指定可选的 NO_WRITE_TO_BINLOG 关键字或其别名 LOCAL。OPTIMIZE TABLE 返回一个结果集,其列如下表所示。 | |
| |
| |
| status, error, info, note 或 warning |
| |
OPTIMIZE TABLE 捕获并抛出任何在将表统计信息从旧文件复制到新创建的文件时发生的错误。例如,如果 .MYD 或 .MYI 文件所有者的用户ID与 mysqld 进程的用户ID不同,则 OPTIMIZE TABLE 会生成 “cannot change ownership of the file” 错误,除非 mysqld 是由 root 用户启动的。对于 InnoDB 表,OPTIMIZE TABLE 映射为 ALTER TABLE ... FORCE,它重建表以更新索引统计信息并释放聚集索引中未使用的空间。在 InnoDB 表上运行 OPTIMIZE TABLE 时,它会显示在输出中,如下所示: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 对常规和分区 InnoDB 表使用 Online DDL,这减少了并发 DML 操作的停机时间。OPTIMIZE TABLE 触发的表重建已在适当位置完成。独占表锁仅在操作的准备阶段和提交阶段短暂使用。在准备阶段,更新元数据并创建中间表。在提交阶段,将提交表元数据更改。OPTIMIZE TABLE 在以下条件下使用表复制方法重建表:● 启用 old_alter_table 系统变量时。● 使用 --skip-new 选项启动服务器时。对于包含 FULLTEXT 索引的 InnoDB 表,OPTIMIZE TABLE 不支持使用 Online DDL。改为使用表复制方法。InnoDB 使用页面分配方法存储数据,不会像传统存储引擎(如 MyISAM)那样出现碎片。在考虑是否运行优化时,请考虑服务器要处理的事务的工作负载:● 预计会出现一定程度的碎片。InnoDB 只填充页的 93%,这是为了更新留出空间,而不必拆分页面。● 删除操作可能会留下空间,使页面的填充量低于预期,这可能会使优化表变得有价值。● 当有足够的空间时,行的更新通常会在同一页中重写数据,具体取决于数据类型和行格式。● 随着时间的推移,高并发工作负载可能会在索引中留下空隙,因为 InnoDB 通过 MVCC 机制保留了相同数据的多个版本。对于 MyISAM 表,OPTIMIZE TABLE 工作方式如下:● 如果表的统计信息不是最新的(并且无法通过排序索引来完成修复),更新它们。对于常规和分区 InnoDB 表,联机执行 OPTIMIZE TABLE。否则,MySQL 会在 OPTIMIZE TABLE 运行期间锁定该表。OPTIMIZE TABLE 不会对R树索引进行排序,例如 POINT 列上的空间索引。https://dev.mysql.com/doc/refman/8.0/en/optimize-table.html