MySQLのテーブル保守ステートメントについて

# TL;DR
MySQLが提供するテーブル保守ステートメントについてまとめました(記事のアクセス日はすべて2024-12-08です)。

1. **ANALYZE TABLE**：インデックス統計情報を更新し、クエリ最適化を支援。  
1. **CHECK TABLE**：テーブル構造やデータ整合性を検証。問題点があれば報告。  
1. **CHECKSUM TABLE**：テーブルデータの整合性比較用チェックサムを取得し、レプリケーションやバックアップの整合性確認に活用。
1. **OPTIMIZE TABLE**：断片化を解消し、I/O効率を向上。
1. **REPAIR TABLE**：破損したデータを修復。MyISAM、ARCHIVE、CSVテーブルのみ対応。

参考: [MySQL :: MySQL 8.4 Reference Manual :: 15.7.3 Table Maintenance Statements](https://dev.mysql.com/doc/refman/8.4/en/table-maintenance-statements.html)

# 1. ANALYZE TABLE ステートメント

`ANALYZE TABLE`もいくつか種類(`UPDATE`や`DROP`と併用するもの)がありますが、今回はもっともかんたんなものについて説明をします。

[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.1 ANALYZE TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/analyze-table.html)に以下の記載があります。

> ANALYZE TABLE without any HISTOGRAM clause performs a key distribution analysis and stores the distribution for the named table or tables. For MyISAM tables, ANALYZE TABLE for key distribution analysis is equivalent to using myisamchk --analyze.

ここで、「キー分布の保存をして一体何が嬉しいのか？」という疑問が出てくるかもしれませんが、これはクエリの実行計画を最適化するための情報を提供するためです。以下では、クエリの実行計画を最適化するために、`ANALYZE TABLE`がどのように役立つのかについて説明します。

## 1.1. MySQLの最適化におけるクエリー実行計画

[MySQL :: MySQL 8.4 Reference Manual :: 10.1 Optimization Overview](https://dev.mysql.com/doc/refman/8.4/en/optimize-overview.html) に最適化に関する記載がありますが、MySQLの最適化の方法は、Databaseレベルでの最適化からハードウェアレベルでの最適化まで様々です。その中でも、クエリの実行計画を最適化することも重要な要素の一つです。

クエリの最適化の一つとして、[MySQL :: MySQL 8.4 Reference Manual :: 10.2.1 Optimizing SELECT Statements](https://dev.mysql.com/doc/refman/8.4/en/select-optimization.html)を読むと`ANALYZE TABLE`を実行しておくことで、`optimizer`が最適なクエリ実行計画を構築するための情報を提供することができると記載があります。

> Keep table statistics up to date by using the ANALYZE TABLE statement periodically, so the optimizer has the information needed to construct an efficient execution plan.

さて、`optimizer`とは何かというと、[MySQL :: MySQL 8.4 Reference Manual :: MySQL Glossary](https://dev.mysql.com/doc/refman/8.4/en/glossary.html#:~:text=The%20MySQL%20component%20that%20determines%20the%20best%20indexes%20and%20join%20order%20to%20use%20for%20a%20query%2C%20based%20on%20characteristics%20and%20data%20distribution%20of%20the%20relevant%20tables.)に次のように記載があります。

> The MySQL component that determines the best indexes and join order to use for a query, based on characteristics and data distribution of the relevant tables.

つまり、クエリの実行を行う際には、`optimizer`が最適なインデックスや結合順序を決定します。そのため、`ANALYZE TABLE`を実行しておくことで、`optimizer`が最適なクエリ実行計画を構築するための情報を提供することができるのです。もし、これを実行しない場合は、`optimizer`が最適なクエリ実行計画を構築するための情報が不足してしまい、パフォーマンスが低下する可能性があります。

公式ドキュメントではないですが、次のブログなどは視覚的で理解しやすいかと思います。

- match1124さん, 2024, [データベースにおけるオプティマイザー（optimizer）とは](https://zenn.dev/tm35/articles/6afc7228756fb3)

# 2. CHECK TABLE ステートメント

[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.2 CHECK TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/check-table.html)を読むと、`CHECK TABLE`はテーブルの構造やデータの整合性を検証するためのステートメントであることがわかります。

> CHECK TABLE checks a table or tables for errors. CHECK TABLE can also check views for problems, such as tables that are referenced in the view definition that no longer exist.

さて、このクエリを実行して検査をしてくれることで、どのようなメリットがあるのでしょうか？

InnoDBの場合か、MyISAMの場合かによって異なりますが、MyISAMの場合でCheckの結果が`OK`でない場合、修復が必要であることがわかります（[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.2 CHECK TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/check-table.html#:~:text=If%20CHECK%20TABLE%20output%20does%20not%20return%20OK%20or%20Table%20is%20already%20up%20to%20date%2C%20you%20should%20normally%20run%20a%20repair%20of%20the%20table.%20See%20Section%C2%A09.6%2C%20%E2%80%9CMyISAM%20Table%20Maintenance%20and%20Crash%20Recovery%E2%80%9D.)）。

> If CHECK TABLE output does not return OK or Table is already up to date, you should normally run a repair of the table. [See Section 9.6, “MyISAM Table Maintenance and Crash Recovery”](https://dev.mysql.com/doc/refman/8.4/en/myisam-table-maintenance.html).

## 2.1. コラム: MyISAMとInnoDBの違い

[MySQL :: MySQL 8.4 Reference Manual :: 18 Alternative Storage Engines](https://dev.mysql.com/doc/refman/8.4/en/storage-engines.html)に詳細は書かれていますが、デフォルトではInnoDBが設定されています。ロックの仕組みについて異なる記述があるため気になった方は参照してみてください。

# 3. CHECKSUM TABLE ステートメント

[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.3 CHECKSUM TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/checksum-table.html)を読むと、`CHECKSUM TABLE`はバックアップした後などに２つのテーブルが同一であるかどうかを確認するためのステートメントであることがわかります。

> CHECKSUM TABLE reports a checksum for the contents of a table. You can use this statement to verify that the contents are the same before and after a backup, rollback, or other operation that is intended to put the data back to a known state.

ただ、大きなテーブルに対して実行すると時間がかかるため、注意が必要のようです（[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.3 CHECKSUM TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/checksum-table.html#:~:text=For%20large%20tables%2C%20this%20could%20take%20a%20long%20time%2C%20thus%20you%20would%20only%20perform%20this%20operation%20occasionally.)）。

# 4. OPTIMIZE TABLE ステートメント

こちらの`OPTIMIZE TABLE`は`ANALYZE TABLE`と違って物理的なテーブルの最適化を行うステートメントです（`ANALYZE TABLE`は飽くまでクエリの最適化のための情報を提供するステートメントであり、物理的なテーブルの最適化を行うものではありません）。

[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.4 OPTIMIZE TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/optimize-table.html)を読むと、`OPTIMIZE TABLE`はI/Oの効率を向上化するために、フラグメント化されたテーブルを再構築するためのステートメントであることがわかります。

> OPTIMIZE TABLE 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 used by that table.

> You can use OPTIMIZE TABLE to reclaim the unused space and to defragment the data file.

# 5. REPAIR TABLE ステートメント

[MySQL :: MySQL 8.4 Reference Manual :: 15.7.3.5 REPAIR TABLE Statement](https://dev.mysql.com/doc/refman/8.4/en/repair-table.html)を読むと、`REPAIR TABLE`はInnoDBはサポートされていません。

> REPAIR TABLE works for MyISAM, ARCHIVE, and CSV tables.

こちらを実行すると、破損したデータを修復することができるようです。

> REPAIR TABLE repairs a possibly corrupted table, for certain storage engines only.

## 感想

普段は「SELECT」や「INSERT」などのクエリを実行さえできればよく、保守や最適化についてはあまり意識していなかったので、今回の調査を通じて、データベースの保守や最適化についての重要性を再認識しました。特にフラグメントなどは大学の授業で学んだことがあるものの、実際に使われている場面を見ることがなかったので、今回の調査を通じて、実務での活用方法を学ぶことができ良かったです。