ホームページ >データベース >mysql チュートリアル >MySQL 用のいくつかのデフラグ ソリューション

MySQL 用のいくつかのデフラグ ソリューション

WBOY
WBOY転載
2022-07-20 14:26:306581ブラウズ

この記事では、mysql に関する関連知識を提供し、主にデフラグ ソリューションに関連する問題、つまり、大量のデータを削除した後にスペースが解放されない問題の解決に対処します。ぜひご覧ください。皆さんのお役に立てれば幸いです。

MySQL 用のいくつかのデフラグ ソリューション

推奨学習: mysql ビデオ チュートリアル

MySQL のいくつかのデフラグ ソリューションの概要 (スペースが解放されない問題を解決するため)大量のデータを削除した後) 質問)

1. 背景知識?

#1.1 なぜフラグメントが存在するのですか?

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

    UPDATE が多数の場合、ファイルの断片化も発生します。Innodb の最小物理ストレージ割り当て単位はページであり、UPDATE によってもページ分割が発生する可能性があります。ページ分割が頻繁に行われると、ページが断片化します。疎になり、不規則に埋められるため、最終的にはデータが断片化します。

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

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

  3. 挿入操作を実行するとき、MySQL は空白スペースを使用しようとしますが、特定の空白スペースが適切なサイズのデータ​​で占有されていない場合、完全に占有することはできません。フラグメンテーション;

  4. 概要:

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

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

        drop、truncate は、ディスク領域がすぐに解放されます。 Innodb と MyISAM です;
        truncate table は、実際には、テーブルを削除してから作成するのと少し似ていますが、テーブルの作成プロセスが最適化されている点が異なります。たとえば、テーブル構造ファイルが次のようになります。以前から存在していた、などしたがって、速度はテーブルのドロップの速度に近い必要があります。
        delete from table_name を実行すると、テーブル内のすべてのデータが削除されます。MyISAM の場合、ディスク領域はすぐに解放されます (特別に処理されるため、より合理的です) )、InnoDB はディスク領域を解放しません;
      1. テーブル名からの削除 (xxx の場合); 条件付き削除では、innodb も MyISAM もディスク領域を解放しません;
      2. 使用します操作テーブル table_name の削除後に最適化すると、ディスク領域がすぐに解放されます。 innodb であっても myisam であっても。したがって、ディスク領域を解放するという目的を達成するには、削除後にテーブルの最適化操作を実行します。
      3. from テーブルを削除してもディスク領域は解放されませんが、この領域は次回データを挿入するときに引き続き使用できます。
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 断片をクリーンアップする (領域を再利用する) 方法

公式文書リファレンス


MySQL 用のいくつかのデフラグ ソリューション

通常有这几种做法

  1. alter table tb_test engine=innodb; (本质上是 recreate)
  2. optimize table tb_test; (本质上是 recreate,但是在不同创建下会有区别)
  3. ALTER TABLE tablename FORCE (在InnoDB表中等价于 alter table tb_test engine=innodb; )
  4. mysqlcheck 批量表空间优化
  5. gh-ost/pt-osc
  6. pt-online-schema-change (本质上也是 先备份旧表数据,然后 truncate 旧表)

1. alter table tb_test engine=innodb 原理介绍

这其实是一个NULL操作,表面上看什么也不做,实际上重新整理碎片了.当执行优化操作时,实际执行的是一个空的 ALTER 命令,但是这个命令也会起到优化的作用,它会重建整个表,删掉未使用的空白空间.

Running ALTER TABLE tbl_name ENGINE=INNODB on an existing InnoDB table performs a “null” ALTER TABLE operation, which can be used to defragment an InnoDB table, as described in Section 15.11.4, “Defragmenting a Table”. Running ALTER TABLE tbl_name FORCE on an InnoDB table performs the same function.

    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. optimize table xxx;

OPTIMIZE TABLE语句可以重新组织表、索引的物理存储,减少存储空间,提高访问的I/O效率。类似于碎片整理功能。

MySQL可以通过optimize table语句释放表空间,重组表数据和索引的物理页,减少表所占空间和优化读写性能

  1. 使用语法

    OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_n说ame [, tbl_name] …

    • 对于主从架构, LOCAL 参数可以让这个过程不写入 binlog ,这样在主库上执行时就不会同步给从库了
    • 默认情况下,MySQL将OPTIMIZE TABLE语句写入二进制日志,以便它们复制到slave服务器。如果不想写二进制日志,使用命令时加上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. **执行时也可以发现报错: Temporary file write failure. **

      建议参考这片文章:
      Mysql optimize table 时报错 Temporary file write failure. 的解决方案

  3. optimize 语句的官网介绍

    • 如果您已经删除了表的一大部分,或者如果您已经对含有可变长度行的表(含有VARCHAR, BLOB或TEXT列的表)进行了很多更改,则应使用 OPTIMIZE TABLE。

    • 被删除的记录被保持在链接清单中,后续的INSERT操作会重新使用旧的记录位置。您可以使用OPTIMIZE TABLE来重新利用未使用的空间,并整理数据文件的碎片。

    • 在多数的设置中,您根本不需要运行OPTIMIZE TABLE。即使您对可变长度的行进行了大量的更新,您也不需要经常运行,每周一次或每月一次 即可,只对特定的表运行。

  4. Mysql 5.6 之前 在OPTIMIZE TABLE运行过程中,MySQL会锁定表,5.6之后有了 Online DDL 则大大减少了锁表时间。

3. alter table、analyze table和optimize table区别

  • alter table tb_test engine = innodb;

    • (也就是 recreate)MySQL 5.5以前用Offline的方式重建表,5.6以后用Online的方式重建表;
  • analyze table tb_test ;

    • 重新统计表的索引信息,不会修改数据,不会重建表,整个过程加MDL读
  • optimize table 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 回だけ行う必要があります。 (現在、毎月午前 4 時にすべての mysql インスタンスのテーブル フラグメントをクリアしています)

推奨学習: mysql ビデオ チュートリアル

以上がMySQL 用のいくつかのデフラグ ソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。