MySQL のいくつかのデフラグ スキームの概要 (大量のデータを削除した後にスペースが解放されない問題を解決するため)
1. 背景知識は?
1.1 なぜ断片が存在するのですか?
-
MySQL での挿入と更新の両方でページ分割が発生する可能性があるため、断片化が存在します。
多数の UPDATE では、ファイルの断片化も発生します。Innodb の最小物理ストレージ割り当て単位はページ (ページ) であり、UPDATE によってページ分割が発生することもあります。ページ分割が頻繁に行われると、ページが疎になり、削除されます。不規則なパディング、そのため、最終的なデータは断片化されます。
-
delete ステートメントは、実際にはデータにマークを付けてリンク リストに記録するだけで、空白スペースが形成されます。
InnoDB では、いくつかの行を削除します。これらの行は「削除済み」としてマークされるだけで、インデックスから物理的に削除されないため、スペースは実際には解放されず、再利用されません。InnoDB のパージ スレッドは、これらの不要なインデックス キーと行を非同期的にクリーンアップします。
-
挿入操作を実行するとき、MySQL は空白スペースを使用しようとしますが、特定の空白スペースが適切なサイズのデータで占有されていない場合、完全に占有することはできず、断片化が形成されます。
-
要約:
-
テーブルの追加、削除、変更操作によりデータ ホールが発生する可能性があるテーブルに対して多数の追加、削除、変更操作が実行されると、データ ホールが発生する可能性が高くなります。
-
MySQL がデータを削除するいくつかの状況と、ディスク領域を解放するかどうか:
- ドロップ、トランケートは、Innodb であっても MyISAM であっても、すぐにディスク領域を解放します。
- テーブルの切り捨ては、実際にはテーブルを削除してから作成するのと少し似ていますが、テーブル構造ファイルがすでに存在するなど、テーブルの作成プロセスが最適化されています。したがって、速度はドロップテーブルの速度に近い必要があります。
- delete from table_name はテーブル内のすべてのデータを削除します。MyISAM の場合、ディスク領域はすぐに解放されます (特別に処理する必要があり、より合理的です)。InnoDB はディスク領域を解放しません。
- delete from table_name where xxx; 条件付き削除の場合、innodb も MyISAM もディスク領域を解放しません。
- 削除操作の後に最適化テーブル table_name を使用すると、ディスク領域がすぐに解放されます。innodb や myisam は関係ありません。したがって、ディスク領域を解放するという目的を達成するには、削除後にテーブルの最適化操作を実行します。
- テーブルからの削除後、ディスク領域は解放されませんが、次回データを挿入するときにこの領域を引き続き使用できます。
-
1.2 断片化によって引き起こされる問題
-
MySQL がデータをスキャンする場合、スキャンされるオブジェクトは実際にはリストの容量要件の上限、つまりデータが書き込まれる領域のピーク位置にある部分です。
-
MySQL データベース内のテーブルに対して複数の削除、更新、挿入が実行されると、テーブルスペースが断片化されます。定期的な表スペースの最適化により、断片化が解消され、表スペースへのアクセスのパフォーマンスが向上します。
-
この種の断片化により、ストレージ コストが増加するだけでなく、データの断片化によりテーブルのスキャン効率も低下します。
-
デフラグを行わないと、長時間ディスク領域を占有し、ディスク使用量がますます増加する可能性があります。
2. ゴミを掃除するにはどうすればよいですか?
問題を解決する前提は、適切な薬を処方するために、まず問題を見つけることです。
2.1. テーブルの断片化を表示する
-
データベース内の断片化されたテーブルをすべて表示する
mysql> select concat('optimize table ',table_schema,'.',table_name,';'),data_free,engine from information_schema.tables where data_free>0 and engine !='MEMORY'; +-----------------------------------------------------------+-----------+--------+ | concat('optimize table ',table_schema,'.',table_name,';') | DATA_FREE | ENGINE | +-----------------------------------------------------------+-----------+--------+ | optimize table abc.t_user_answer; | 2097152 | InnoDB | | optimize table mysql.time_zone_transition; | 4194304 | InnoDB | | optimize table mysql.time_zone_transition_type; | 4194304 | InnoDB | | optimize table mysql.user; | 4194304 | InnoDB | 。。。。
-
指定されたテーブルの断片化を表示する
mysql> show table status like 't_user'\G *************************** 1. row *************************** Name: t_user Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 4333 Avg_row_length: 589 Data_length: 2555904 Max_data_length: 0 Index_length: 2719744 Data_free: 4194304 Auto_increment: NULL Create_time: 2021-11-19 10:13:31 Update_time: 2022-04-20 14:28:42 Check_time: NULL Collation: utf8mb4_general_ci Checksum: NULL Create_options: Comment: 1 row in set (0.00 sec)
Data_free: 4194304 はフラグメントのバイト数を表します。データ テーブルが頻繁に削除されると、多数の Data_free がレコードを頻繁に削除したり、可変長フィールドを含むテーブルを変更したりする原因になります。
-
最も断片化されたテーブルを見つける
SELECT table_schema, TABLE_NAME, concat(data_free/1024/1024, 'M') as data_free FROM `information_schema`.tables WHERE data_free > 3 * 1024 * 1024 AND ENGINE = 'innodb' ORDER BY data_free DESC
2.2 瓦礫の撤去(空間の再生)方法
通常、いくつかの方法があります
- alter table tb_test Engine=innodb; (基本的に再作成)
- optimize table tb_test; (基本的に再作成しますが、異なる作成では違いが生じます)
- ALTER TABLE tablename FORCE ( InnoDB テーブルの alter table tb_test Engine=innodb; と同等)
- mysqlcheckバッチテーブルスペースの最適化
- gh-ost/pt-osc
- pt-online-schema-change (基本的には、最初に古いテーブル データをバックアップし、次に古いテーブルを切り詰めます)
1.テーブル tb_test Engine=innodb を変更する原理の概要
これは実際には NULL 操作であり、表面上は何も行いませんが、実際にはフラグメントを再編成します。最適化操作を実行するとき、実際に実行されるのは空の ALTER コマンドですが、このコマンドは最適化の役割も果たします。テーブル全体を削除し、未使用の空きスペースを削除します。
既存の InnoDB テーブルでALTER TABLE tbl_name ENGINE=INNODB を実行すると、「null」の ALTER TABLE 操作が実行されます。これは、セクション15.11.4「テーブルのデフラグ」で説明されているように、InnoDB テーブルのデフラグに使用できます。InnoDB テーブルでALTER TABLE tbl_name FORCE を実行すると、同じ機能が実行されます。
MySQL5.6 开始采用 Inplace 方式重建表,Alter 期间,支持 DML 查询和更新操作,语句为 alter table t engine=innodb, ALGORITHM=inplace;之所以支持 DML 更新操作,是因为数据拷贝期间会将 DML 更新操作记录到 Row log 中。
重建过程中最耗时的就是拷贝数据的过程,这个过程中支持 DML 查询和更新操作,对于整个 DDL 来说,锁时间很短,就可以近似认为是 Online DDL。
执行过程:
1、获取 MDL(Meta Data Lock)写锁,innodb 内部创建与原表结构相同的临时文件
2、拷贝数据之前,MDL 写锁退化成 MDL 读锁,支持 DML 更新操作
3、根据主键递增顺序,将一行一行的数据读出并写入到临时文件,直至全部写入完成。并且,会将拷贝期间的 DML 更新操作记录到 Row log 中
4、上锁,再将 Row log 中的数据应用到临时文件
5、互换原表和临时表表名
6、删除临时表
2. テーブル xxx を最適化します。
OPTIMIZE TABLE ステートメントは、テーブルとインデックスの物理ストレージを再編成し、ストレージ領域を削減し、アクセス I/O 効率を向上させることができます。デフラグ機能と似ています。
MySQL はステートメントを通じてテーブルスペースを解放しoptimize table
、テーブルデータとインデックスの物理ページを再編成し、テーブルが占有するスペースを削減し、読み取りおよび書き込みパフォーマンスを最適化します。
-
構文を使用する
最適化 [ローカル | NO_WRITE_TO_BINLOG] TABLE tbl_n说ame [, tbl_name] …
- マスター/スレーブ アーキテクチャの場合、LOCAL パラメーターにより、このプロセスが binlog に書き込まれないようにすることができます。これにより、プロセスがマスター ライブラリで実行されるときにスレーブ ライブラリに同期されなくなります。
- デフォルトでは、MySQL は OPTIMIZE TABLE ステートメントをバイナリ ログに書き込み、スレーブ サーバーに複製します。バイナリ ログを書き込みたくない場合は、コマンドの使用時に NO_WRITE_To_BINLOG または LOCAL キーワードを追加できます。
- このステートメントを使用するには、ターゲット テーブルに対する SELECT 権限と INSERT 権限が必要です。
-
知らせ:
-
OPTIMIZE TABLE には十分なスペースが必要です。(残りのスペースは OPTIMIZE テーブルのサイズを超える必要があります)
-
OPTIMIZE は、独立テーブルスペース (innodb_file_per_table=1) にのみ役立ち、共有テーブルスペースには役に立ちません。
共有テーブルスペースの場合、スリム化する必要がある場合: データをエクスポートし、ibdata1 を削除し、innodb_file_per_table を独立テーブルスペースとして設定してから、データをインポートする必要があります。
-
InnoDB テーブルの場合、OPTIMIZE TABLE は次のように機能します。
InnoDB テーブルの場合、OPTIMIZE TABLE は ALTER TABLE ... FORCE (または、このように変換すると、InnoDB テーブルの同等の 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 | +----------+----------+----------+---------------------------------------+ # 但这个提示语可以忽略,从严格的意义讲,说InnoDB不支持optimize table,其实不太准确。 因为 MYSQL的文档说明了,当INNODB 的表,MYSQL会以 ALTER TABLE force + analyze 去执行这个命令(相当于做了recreate和analyze)。 所以最终还是会看到 OK 的状态。 # https://stackoverflow.com/questions/30635603/what-does-table-does-not-support-optimize-doing-recreate-analyze-instead-me
-
MYISAM テーブルの場合、OPTIMIZE TABLE は次のように機能します。
1. テーブルの行が削除されているか分離されている場合は、テーブルを修復します。
2. インデックス ページがソートされていない場合は、インデックス ページをソートします。
3. テーブルの統計が最新でない場合 (インデックスを並べ替えても修復できない場合)、統計を更新します。 -
**実行中にエラーが見つかることもあります: 一時ファイルの書き込み失敗**
この記事を参照することをお勧めします:
Mysql 最適化テーブルがエラーを報告する 一時ファイルの書き込み失敗。
-
-
公式サイトのoptimizeステートメントの紹介
-
テーブルの大部分を削除した場合、または可変長行を含むテーブル (VARCHAR、BLOB、または TEXT 列を含むテーブル) に多くの変更を加えた場合は、OPTIMIZE TABLE を使用する必要があります。
-
削除されたレコードはリンクされたリストに保持され、後続の INSERT 操作では古いレコードの場所が再利用されます。OPTIMIZE TABLE を使用すると、未使用の領域を再利用し、データ ファイルをデフラグできます。
-
ほとんどのセットアップでは、OPTIMIZE TABLE を実行する必要はまったくありません。可変長行に対して大量の更新を行う場合でも、特定のテーブルに対してのみ、毎週または毎月、それほど頻繁に更新を実行する必要はありません。
-
-
MySQL 5.6 より前では、MySQL は OPTIMIZE TABLE の操作中にテーブルをロックしていましたが、5.6 以降では、オンライン DDL を使用することで、テーブルのロックにかかる時間が大幅に短縮されました。
3. テーブルの変更、テーブルの分析、テーブルの最適化の違い
-
テーブル tb_test エンジン = innodb を変更します。
- (つまり、再作成します) MySQL 5.5 より前は、テーブルがオフライン モードで再構築され、5.6 以降は、テーブルがオンライン モードで再構築されました。
-
テーブル tb_test を分析します ;
- テーブルのインデックス情報は再記述され、データは変更されず、テーブルは再構築されず、プロセス全体が MDL によって読み取られます。
-
テーブル tb_test を最適化します。
- alter table xxx = innodb; +analyze table xxx; の処理です。
4. OPTIMIZE TABLE と ALTER TABLE xxxx ENGINE= INNODB のどちらが良いですか
- OPTIMIZE TABLE または ALTER TABLE xxxx ENGINE= INNODB は基本的に同じです。ただし、場合によっては、ALTER TABLE xxxx ENGINE= INNODB の方が優れています。
- 例: old_alter_table システム変数が有効になっていないなど。
- さらに、MyISAM タイプのテーブルの場合、ALTER TABLE xxxx ENGINE= INNODB を使用する方が、OPTIMIZE TABLE より明らかに優れています。
2.3 公式推奨事項
MySQL は公式に、デフラグを頻繁に (1 時間ごとまたは毎日) 行わないことを推奨しています。実際の状況によれば、一般に、デフラグは週に 1 回または月に 1 回だけで済みます (現在、すべての mysql インスタンスのテーブル フラグメントを 4:00 にクリーンアップしています)毎月午前中)