MySQL のいくつかのデフラグ スキームの概要 (大量のデータを削除した後にスペースが解放されない問題を解決するため)

MySQL のいくつかのデフラグ スキームの概要 (大量のデータを削除した後にスペースが解放されない問題を解決するため)

1. 背景知識は?

1.1 なぜ断片が存在するのですか?

  1. MySQL での挿入と更新の両方でページ分割が発生する可能性があるため、断片化が存在します。

    多数の UPDATE では、ファイルの断片化も発生します。Innodb の最小物理ストレージ割り当て単位はページ (ページ) であり、UPDATE によってページ分割が発生することもあります。ページ分割が頻繁に行われると、ページが疎になり、削除されます。不規則なパディング、そのため、最終的なデータは断片化されます。

  2. delete ステートメントは、実際にはデータにマークを付けてリンク リストに記録するだけで、空白スペースが形成されます。

    InnoDB では、いくつかの行を削除します。これらの行は「削除済み」としてマークされるだけで、インデックスから物理的に削除されないため、スペースは実際には解放されず、再利用されません。InnoDB のパージ スレッドは、これらの不要なインデックス キーと行を非同期的にクリーンアップします。

  3. 挿入操作を実行するとき、MySQL は空白スペースを使用しようとしますが、特定の空白スペースが適切なサイズのデータ​​で占有されていない場合、完全に占有することはできず、断片化が形成されます。

  4. 要約:

    1. テーブルの追加、削除、変更操作によりデータ ホールが発生する可能性があるテーブルに対して多数の追加、削除、変更操作が実行されると、データ ホールが発生する可能性が高くなります。

    2. MySQL がデータを削除するいくつかの状況と、ディスク領域を解放するかどうか:

      1. ドロップ、トランケートは、Innodb であっても MyISAM であっても、すぐにディスク領域を解放します。
      • テーブルの切り捨ては、実際にはテーブルを削除してから作成するのと少し似ていますが、テーブル構造ファイルがすでに存在するなど、テーブルの作成プロセスが最適化されています。したがって、速度はドロップテーブルの速度に近い必要があります。
      1. delete from table_name はテーブル内のすべてのデータを削除します。MyISAM の場合、ディスク領域はすぐに解放されます (特別に処理する必要があり、より合理的です)。InnoDB はディスク領域を解放しません。
      2. delete from table_name where xxx; 条件付き削除の場合、innodb も MyISAM もディスク領域を解放しません。
      3. 削除操作の後に最適化テーブル table_name を使用すると、ディスク領域がすぐに解放されます。innodb や myisam は関係ありません。したがって、ディスク領域を解放するという目的を達成するには、削除後にテーブルの最適化操作を実行します。
      4. テーブルからの削除後、ディスク領域は解放されませんが、次回データを挿入するときにこの領域を引き続き使用できます。

1.2 断片化によって引き起こされる問題

  • MySQL がデータをスキャンする場合、スキャンされるオブジェクトは実際にはリストの容量要件の上限、つまりデータが書き込まれる領域のピーク位置にある部分です。

  • MySQL データベース内のテーブルに対して複数の削除、更新、挿入が実行されると、テーブルスペースが断片化されます。定期的な表スペースの最適化により、断片化が解消され、表スペースへのアクセスのパフォーマンスが向上します。

  • この種の断片化により、ストレージ コストが増加するだけでなく、データの断片化によりテーブルのスキャン効率も低下します。

  • デフラグを行わないと、長時間ディスク領域を占有し、ディスク使用量がますます増加する可能性があります。

2. ゴミを掃除するにはどうすればよいですか?

問題を解決する前提は、適切な薬を処方するために、まず問題を見つけることです。

2.1. テーブルの断片化を表示する

  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 |
    。。。。
    
  2. 指定されたテーブルの断片化を表示する

     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 がレコードを頻繁に削除したり、可変長フィールドを含むテーブルを変更したりする原因になります。

  3. 最も断片化されたテーブルを見つける

    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 瓦礫の撤去(空間の再生)方法

公式ドキュメントのリファレンス
ここに画像の説明を挿入

通常、いくつかの方法があります

  1. alter table tb_test Engine=innodb; (基本的に再作成)
  2. optimize table tb_test; (基本的に再作成しますが、異なる作成では違いが生じます)
  3. ALTER TABLE tablename FORCE ( InnoDB テーブルの alter table tb_test Engine=innodb; と同等)
  4. mysqlcheckバッチテーブルスペースの最適化
  5. gh-ost/pt-osc
  6. 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、テーブルデータとインデックスの物理ページを再編成し、テーブルが占有するスペースを削減し、読み取りおよび書き込みパフォーマンスを最適化します。

  1. 構文を使用する

    最適化 [ローカル | NO_WRITE_TO_BINLOG] TABLE tbl_n说ame [, tbl_name] …

    • マスター/スレーブ アーキテクチャの場合、LOCAL パラメーターにより、このプロセスが binlog に書き込まれないようにすることができます。これにより、プロセスがマスター ライブラリで実行されるときにスレーブ ライブラリに同期されなくなります。
    • デフォルトでは、MySQL は OPTIMIZE TABLE ステートメントをバイナリ ログに書き込み、スレーブ サーバーに複製します。バイナリ ログを書き込みたくない場合は、コマンドの使用時に NO_WRITE_To_BINLOG または LOCAL キーワードを追加できます。
    • このステートメントを使用するには、ターゲット テーブルに対する SELECT 権限と INSERT 権限が必要です。
  2. 知らせ:

    1. OPTIMIZE TABLE には十分なスペースが必要です。(残りのスペースは OPTIMIZE テーブルのサイズを超える必要があります)

    2. OPTIMIZE は、独立テーブルスペース (innodb_file_per_table=1) にのみ役立ち、共有テーブルスペースには役に立ちません。

      共有テーブルスペースの場合、スリム化する必要がある場合: データをエクスポートし、ibdata1 を削除し、innodb_file_per_table を独立テーブルスペースとして設定してから、データをインポートする必要があります。

    3. 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
      
    4. MYISAM テーブルの場合、OPTIMIZE TABLE は次のように機能します。
      1. テーブルの行が削除されているか分離されている場合は、テーブルを修復します。
      2. インデックス ページがソートされていない場合は、インデックス ページをソートします。
      3. テーブルの統計が最新でない場合 (インデックスを並べ替えても修復できない場合)、統計を更新します。

    5. **実行中にエラーが見つかることもあります: 一時ファイルの書き込み失敗**

      この記事を参照することをお勧めします:
      Mysql 最適化テーブルがエラーを報告する 一時ファイルの書き込み失敗。

  3. 公式サイトのoptimizeステートメントの紹介

    • テーブルの大部分を削除した場合、または可変長行を含むテーブル (VARCHAR、BLOB、または TEXT 列を含むテーブル) に多くの変更を加えた場合は、OPTIMIZE TABLE を使用する必要があります。

    • 削除されたレコードはリンクされたリストに保持され、後続の INSERT 操作では古いレコードの場所が再利用されます。OPTIMIZE TABLE を使用すると、未使用の領域を再利用し、データ ファイルをデフラグできます。

    • ほとんどのセットアップでは、OPTIMIZE TABLE を実行する必要はまったくありません。可変長行に対して大量の更新を行う場合でも、特定のテーブルに対してのみ、毎週または毎月、それほど頻繁に更新を実行する必要はありません。

  4. 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 にクリーンアップしています)毎月午前中)

おすすめ

転載: blog.csdn.net/UserFrank/article/details/124711275