#### 13.7.3.4 OPTIMIZE TABLE Statement

[]()[]()[]()

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

[`OPTIMIZE TABLE`](optimize-table.html) reorganizes the physical storage of table data and associated index data, to reduce storage space and improve I/O efficiency when accessing the table. The exact changes made to each table depend on the [storage engine](glossary.html#glos_storage_engine) used by that table.

 Use [`OPTIMIZE TABLE`](optimize-table.html) in these cases, depending on the type of table:

* After doing substantial insert, update, or delete operations on an `InnoDB` table that has its own [.ibd file](glossary.html#glos_ibd_file) because it was created with the [`innodb_file_per_table`](innodb-parameters.html#sysvar_innodb_file_per_table) option enabled. The table and indexes are reorganized, and disk space can be reclaimed for use by the operating system.

* After doing substantial insert, update, or delete operations on columns that are part of a `FULLTEXT` index in an `InnoDB` table. Set the configuration option [`innodb_optimize_fulltext_only=1`](innodb-parameters.html#sysvar_innodb_optimize_fulltext_only) first. To keep the index maintenance period to a reasonable time, set the [`innodb_ft_num_word_optimize`](innodb-parameters.html#sysvar_innodb_ft_num_word_optimize) option to specify how many words to update in the search index, and run a sequence of `OPTIMIZE TABLE` statements until the search index is fully updated.

* After deleting a large part of a `MyISAM` or `ARCHIVE` table, or making many changes to a `MyISAM` or `ARCHIVE `table with variable-length rows (tables that have [`VARCHAR`](char.html), [`VARBINARY`](binary-varbinary.html), [`BLOB`](blob.html), or [`TEXT`](blob.html) columns). Deleted rows are maintained in a linked list and subsequent [`INSERT`](insert.html) operations reuse old row positions. You can use [`OPTIMIZE TABLE`](optimize-table.html) to reclaim the unused space and to defragment the data file. After extensive changes to a table, this statement may also improve performance of statements that use the table, sometimes significantly.

 This statement requires [`SELECT`](privileges-provided.html#priv_select) and [`INSERT`](privileges-provided.html#priv_insert) privileges for the table.

[`OPTIMIZE TABLE`](optimize-table.html) works for [`InnoDB`](innodb-storage-engine.html), [`MyISAM`](myisam-storage-engine.html), and [`ARCHIVE`](archive-storage-engine.html) tables. [`OPTIMIZE TABLE`](optimize-table.html) is also supported for dynamic columns of in-memory [`NDB`](mysql-cluster.html) tables. It does not work for fixed-width columns of in-memory tables, nor does it work for Disk Data tables. The performance of `OPTIMIZE` on NDB Cluster tables can be tuned using [`--ndb-optimization-delay`](mysql-cluster-options-variables.html#option_mysqld_ndb-optimization-delay), which controls the length of time to wait between processing batches of rows by [`OPTIMIZE TABLE`](optimize-table.html). For more information, see [Section 23.2.7.11, “Previous NDB Cluster Issues Resolved in NDB Cluster 8.0”](mysql-cluster-limitations-resolved.html).

 For NDB Cluster tables, [`OPTIMIZE TABLE`](optimize-table.html) can be interrupted by (for example) killing the SQL thread performing the `OPTIMIZE` operation.

 By default, [`OPTIMIZE TABLE`](optimize-table.html) does *not* work for tables created using any other storage engine and returns a result indicating this lack of support. You can make [`OPTIMIZE TABLE`](optimize-table.html) work for other storage engines by starting [**mysqld**](mysqld.html) with the [`--skip-new`](server-options.html#option_mysqld_skip-new) option. In this case, [`OPTIMIZE TABLE`](optimize-table.html) is just mapped to [`ALTER TABLE`](alter-table.html).

 This statement does not work with views.

[`OPTIMIZE TABLE`](optimize-table.html) is supported for partitioned tables. For information about using this statement with partitioned tables and table partitions, see [Section 24.3.4, “Maintenance of Partitions”](partitioning-maintenance.html).

 By default, the server writes [`OPTIMIZE TABLE`](optimize-table.html) statements to the binary log so that they replicate to replicas. To suppress logging, specify the optional `NO_WRITE_TO_BINLOG` keyword or its alias `LOCAL`.

* [OPTIMIZE TABLE Output](optimize-table.html#optimize-table-output)

* [InnoDB Details](optimize-table.html#optimize-table-innodb-details)

* [MyISAM Details](optimize-table.html#optimize-table-myisam-details)

* [Other Considerations](optimize-table.html#optimize-table-other-considerations)

##### OPTIMIZE TABLE Output

[`OPTIMIZE TABLE`](optimize-table.html) returns a result set with the columns shown in the following table.

|  Column  |                     Value                     |
|----------|-----------------------------------------------|
| `Table`  |                The table name                 |
|   `Op`   |               Always `optimize`               |
|`Msg_type`|`status`, `error`, `info`, `note`, or `warning`|
|`Msg_text`|           An informational message            |

[`OPTIMIZE TABLE`](optimize-table.html) table catches and throws any errors that occur while copying table statistics from the old file to the newly created file. For example. if the user ID of the owner of the `.MYD` or `.MYI` file is different from the user ID of the [**mysqld**](mysqld.html) process, [`OPTIMIZE TABLE`](optimize-table.html) generates a "cannot change ownership of the file" error unless [**mysqld**](mysqld.html) is started by the `root` user.

##### InnoDB Details

 For `InnoDB` tables, [`OPTIMIZE TABLE`](optimize-table.html) is mapped to [`ALTER TABLE ... FORCE`](alter-table.html), which rebuilds the table to update index statistics and free unused space in the clustered index. This is displayed in the output of [`OPTIMIZE TABLE`](optimize-table.html) when you run it on an `InnoDB` table, as shown here:

```
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`](optimize-table.html) uses [online DDL](innodb-online-ddl.html) for regular and partitioned `InnoDB` tables, which reduces downtime for concurrent DML operations. The table rebuild triggered by [`OPTIMIZE TABLE`](optimize-table.html) is completed in place. An exclusive table lock is only taken briefly during the prepare phase and the commit phase of the operation. During the prepare phase, metadata is updated and an intermediate table is created. During the commit phase, table metadata changes are committed.

[`OPTIMIZE TABLE`](optimize-table.html) rebuilds the table using the table copy method under the following conditions:

* When the [`old_alter_table`](server-system-variables.html#sysvar_old_alter_table) system variable is enabled.

* When the server is started with the [`--skip-new`](server-options.html#option_mysqld_skip-new) option.

[`OPTIMIZE TABLE`](optimize-table.html) using [online DDL](innodb-online-ddl.html) is not supported for `InnoDB` tables that contain `FULLTEXT` indexes. The table copy method is used instead.

`InnoDB` stores data using a page-allocation method and does not suffer from fragmentation in the same way that legacy storage engines (such as `MyISAM`) do. When considering whether or not to run optimize, consider the workload of transactions that your server is expected to process:

* Some level of fragmentation is expected. `InnoDB` only fills [pages](glossary.html#glos_page) 93% full, to leave room for updates without having to split pages.

* Delete operations might leave gaps that leave pages less filled than desired, which could make it worthwhile to optimize the table.

* Updates to rows usually rewrite the data within the same page, depending on the data type and row format, when sufficient space is available. See [Section 15.9.1.5, “How Compression Works for InnoDB Tables”](innodb-compression-internals.html) and [Section 15.10, “InnoDB Row Formats”](innodb-row-format.html).

* High-concurrency workloads might leave gaps in indexes over time, as `InnoDB` retains multiple versions of the same data due through its [MVCC](glossary.html#glos_mvcc) mechanism. See [Section 15.3, “InnoDB Multi-Versioning”](innodb-multi-versioning.html).

##### MyISAM Details

 For `MyISAM` tables, [`OPTIMIZE TABLE`](optimize-table.html) works as follows:

1. If the table has deleted or split rows, repair the table.

2. If the index pages are not sorted, sort them.

3. If the table's statistics are not up to date (and the repair could not be accomplished by sorting the index), update them.

##### Other Considerations

[`OPTIMIZE TABLE`](optimize-table.html) is performed online for regular and partitioned `InnoDB` tables. Otherwise, MySQL [locks the table](glossary.html#glos_table_lock) during the time [`OPTIMIZE TABLE`](optimize-table.html) is running.

[`OPTIMIZE TABLE`](optimize-table.html) does not sort R-tree indexes, such as spatial indexes on `POINT` columns. (Bug #23578)

