MySQL でデータを削除してもテーブル ファイルのサイズが変更されないのはなぜですか?

MySQL でデータを削除してもテーブル ファイルのサイズが変更されないのはなぜですか?

長期間稼働しているデータベースの場合、テーブルがストレージ領域を占有しすぎるという問題がよく発生します。ただし、多くの不要なテーブルを削除した後も、テーブルファイルのサイズは変わりません。この問題を解決するには、InnoDB がテーブル領域を再利用する方法を理解する必要があります。

テーブルの場合、占有されるスペースは主にテーブル構造とテーブル データの 2 つの部分に分かれます。一般的に、テーブル構造の定義はごくわずかなスペースしか占有しません。したがって、スペースの問題は主にテーブル データに関連しています。

MySQL 8.0 より前では、テーブル構造は .frm サフィックスを持つファイルに保存されていました。 8.0 では、システム データ テーブルでテーブル構造を定義できるようになりました。

テーブルデータの保存について

テーブル データは、共有テーブルスペースまたはinnodb_file_per_tableによって制御される別のファイルに保存できます。

  • OFFの場合は、データディクショナリとともにシステム共有表領域に存在することを意味します。
  • ONの場合、各InnoDBテーブル構造は.idbという拡張子のファイルに保存されます。

5.6.6 以降では、デフォルト値は ON です。

このパラメータを ON に設定することをお勧めします。これにより、必要がない場合に、システムが drop table コマンドを通じてファイルを直接削除します。

ただし、共有表領域では、表が削除されても、領域は再利用されません。

切り捨てる = 削除する + 作成する

データ削除プロセス

ただし、 deleteを使用してデータを削除すると、一部の行のみが削除され、表スペースが再利用されない場合があります。

MySQL InnoDB は、データを格納するための構造として B+ ツリー (インデックス構成テーブルとも呼ばれる) を使用し、データはページに格納されることがわかっています。

データを削除する場合、次の 2 つの状況があります。

  • データページ内のいくつかのレコードを削除する
  • データページ全体の内容を削除する

たとえば、レコード R4 を削除する場合は、次のようにします。

InnoDB は、再利用可能な場所と呼ばれるレコード R4 を直接削除済みとしてマークします。その後、ID が 300 ~ 700 のレコードが挿入されると、その位置は再利用されます。ディスクファイルのサイズは縮小されないことがわかります。

さらに、レコードの再利用は、スコープ条件を満たすデータに限定されます。後で ID 800 のレコードを挿入する場合、R4 の位置は再利用できません。

別の例として、データ ページ全体の内容が削除される場合、ページ A のデータ ページである R3、R4、R5 が削除されるとします。

この時点で、InnoDB はページ A 全体を削除済みとしてマークし、スコープ制限なしにデータ全体を再利用できるようになります。たとえば、ID=50 のコンテンツを挿入する場合は、それを直接再利用できます。

また、隣接する 2 つのデータ ページの使用率が非常に低い場合、2 つのページのデータはいずれかのページにマージされ、もう一方のページは再利用可能としてマークされます。

要約すると、データ行またはデータ ページが削除された場合、再利用のために削除済みとしてマークされるため、ファイル サイズは縮小されません。対応する具体的な操作は、削除コマンドを使用することです。

さらに、レコードを削除する最初のケースでは、R4 を削除して ID=800 を挿入するなど、再利用時の範囲制限により多くのギャップが発生することもわかります。

挿入操作によってギャップも生じる

データを挿入する際に、インデックスの昇順でデータを挿入すると、インデックスの構造がコンパクトになります。ただし、ランダムに挿入すると、インデックス データ ページが分割される可能性があります。

たとえば、いっぱいになっているページ A にデータを挿入します。

ページ A がいっぱいなので、ページ B を申請する必要があります。ページ A をページ B に調整するプロセスは、ページ分割とも呼ばれます。

終了後、ページAに隙間ができます。

さらに、更新操作の場合、最初に削除してから挿入するとギャップが発生します。

さらに、追加、削除、変更が大量に行われたテーブルでは、穴があいてしまう可能性があります。穴をなくすと自然な空間が生まれます。

テーブルの再構築を使用する

テーブル内のギャップを削除するには、テーブル A と同じ構造のテーブル B を再構築し、主キー ID の昇順でデータをテーブル B に挿入します。

挿入は順次行われるため、当然テーブル B にギャップはなく、データ ページの使用率も高くなります。その後、テーブル B がテーブル A の代わりに使用され、テーブル A のスペースが縮小される効果があるように見えました。

具体的には、次のとおりです。

テーブルAを変更するエンジン=InnoDB

バージョン 5.5 以降では、コマンドは上記のプロセスと同様になり、MySQL はデータ交換、テーブル名交換、古いテーブルの削除の操作を自動的に完了します。

しかし、問題があります。DDLではテーブルAを更新できません。この時にテーブルAにデータを書き込むと、データ損失が発生します。

オンライン DDL はバージョン 5.6 以降で導入されました。

オンラインDDL

Online DDL はこれに基づいて次の更新を行いました。

テーブルを再構築するプロセスは次のとおりです。

  1. 一時ファイルを作成し、テーブル A の主キーのすべてのデータ ページをスキャンします。
  2. 生成されたデータ ページを使用して B+ ツリーを生成し、一時ファイルに保存します。
  3. 一時ファイルを生成する際に、A に対して操作があった場合は、図の状態 2 に該当し、ログ ファイルに記録されます。
  4. 一時ファイルが生成された後、ログ ファイルが一時ファイルに適用され、状態 3 に対応するテーブル A と同じデータ ファイルが取得されます。
  5. A テーブルのデータ ファイルを一時ファイルに置き換えます。

行ログ ファイルが存在するため、再構築中にテーブル A に対して DML 操作を実行できます。

変更ステートメントが実行される前に、最初に MDL 書き込みロックが要求されますが、データのコピー前に MDL 読み取りロックに退化し、DML 操作をサポートすることに注意してください。

MDL が削除されない理由は、他のスレッドが同時にこのテーブルに対して DDL 操作を実行するのを防ぐためです。

大きなテーブルの場合、この操作は大量の IO および CPU リソースを消費するため、オンライン操作を実行する場合は操作時間を制御する必要があります。安全を確保するために、移行には gh-ost を使用することをお勧めします。

オンラインとインプレース

まず、インプレースとコピーの違いについて説明します。

オンライン DDL では、テーブル A の再構築されたデータは、InnoDB 内に作成された一時ファイルである tmp_file に配置されます。 DDL 全体は InnoDB 内で実行されます。また、サーバー層では、一時テーブルにデータは移動されません。これは「インプレース」操作であるため、「インプレース」と呼ばれます。

前の共通DDLでは、作成されたテーブルAはサーバーによってtmp_tableに作成されるため、「コピー」と呼ばれます。

対応する文は実際には次のようになります。

-- alter table t engine=InnoDB デフォルトは alter table t engine=innodb,ALGORITHM=inplace; です。

-- プロセスはサーバー コピーです alter table t engine=innodb,ALGORITHM=copy;

inplace と online は対応する関係ではないことに注意してください。

  1. DDLプロセスがオンラインの場合、インプレースで実行する必要があります。
  2. インプレース DDL の場合は、<= 8.0 でフルテキスト インデックスや空間インデックスを追加するなど、オンラインにしないでください。

拡大する

最適化、分析、およびテーブル変更の違いについて説明します。

  1. alter table t engine = InnoDB (つまり、再作成) は、デフォルトでオンライン DDL プロシージャを使用します。
  2. analyze table t はテーブルを再構築しません。データを変更せずにテーブルのインデックス情報のみを再計算します。このプロセス中に、MDL 読み取りロックが追加されます。
  3. テーブル t の最適化は、前の 2 つの手順の操作と同等です。

トランザクションでalter tableを使用すると、トランザクションの一貫性を維持するために、デフォルトでトランザクションが自動的にコミットされます。

テーブルを作り直した後、スペースが狭くなるだけでなく、少し広くなることもあります。これは、再構築されたテーブル自体にギャップがないためです。DDL 期間中に、いくつかの DML 実行によって新しいギャップが発生しました。

InnoDB はテーブル全体を埋めることはなく、各ページの 1/16 を後続の更新用に残します。そのため、最初はコンパクトであっても、再構築後にはギャップが生じます。

要約する

これで、delete を使用してデータを削除しても、対応するデータ行は実際には削除されないことがわかりました。InnoDB はそれを再利用可能としてマークするだけなので、テーブル スペースは小さくなりません。

一般的に、再利用されたスペースをマークする方法は 2 つあります。1 つは、データ ページ内の特定の場所のみを削除済みとしてマークする方法ですが、このような場所は特定の範囲内でのみ使用されるため、ギャップが発生します。

もう 1 つは、データ ページ全体を再利用可能としてマークすることです。このようなデータ ページには制限がなく、直接再利用できます。

この問題を解決するには、テーブルを再構築する方法を使用できます。バージョン 5.6 以降では、テーブルの作成はオンライン操作をサポートしていますが、最終的にはビジネスの低ピーク時に使用されます。

上記は、MySQL がデータを削除した後もテーブル ファイル サイズが変更されない理由の詳細です。MySQL テーブル ファイル サイズの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MyBatis バッチによる MySql データの挿入/変更/削除
  • 誤って削除されたデータを復元するための mysqlbinlog コマンドを使用した mysql の実装
  • mysql5.7.33 で誤って ibdata ファイルを削除した後にデータを回復する方法
  • MySQLデータベースは重複データを削除し、メソッドインスタンスを1つだけ保持します
  • MySQL の大きなテーブルで大量のデータを一括削除する方法
  • MySQLがデータの削除を推奨しない理由
  • MySQL 内の数千万のデータを一括削除する Python スクリプト
  • MySQL のデータ削除とデータ テーブル メソッドの例
  • MySQL で大量のデータ (数千万) を素早く削除するためのいくつかの実用的なソリューションの詳細な説明
  • MySQLでデータを削除してもディスク領域が解放されないのはなぜですか

<<:  Vue2とVue3の兄弟コンポーネント通信バスの違いと使い方

>>:  Tomcatの動作原理を分析する

推薦する

Dockerを使用して分散lnmpイメージを作成する

目次1. Docker分散lnmpイメージ生成1. Nginx、MySQL、PHPコンテナを実行する...

SpringBoot プロジェクトの Docker クイック デプロイメントの紹介

1. Dockerをインストールするまず Linux 環境を開き、次のコマンドを入力してインストール...

HTML+CSSプロジェクト開発経験概要(推奨)

ここ数日ブログを更新していませんでした。簡単な HTML+CSS プロジェクトを終えたところです。数...

Vue 3 カスタムディレクティブ開発の概要

指令とは何ですか? Angular と Vue はどちらもディレクティブの概念を持っており、これは通...

MySQL 5.7 解凍版のインストール、アンインストール、および文字化けしたコードの問題のグラフィック解決

1. 解凍版のインストール(1)圧縮パッケージをダウンロードし、ディスクの場所に解凍します。圧縮パッ...

Linuxはデュアルネットワークカードボンドとドライバーインターフェースを使用する

債券とは何かNIC ボンドは、実稼働シナリオでよく使用されるテクノロジーです。複数の NIC を 1...

Linuxロスレス展開方法

概要クラウド プラットフォームのお客様のサーバーでは、業務量が拡大し続けるとディスク容量が不足する場...

シェル スクリプトを使用してワンクリックで MySQL 5.7.29 をインストールする方法

この記事は51CTOブログの著者wjw555の作品を参照しています。スクリプトの内容: vim イン...

CentOS 6.5 インストール mysql5.7 チュートリアル

1. 新機能MySQL 5.7 はエキサイティングなマイルストーンです。デフォルトの InnoDB ...

XHTMLはHTMLのいくつかの廃止された要素を使用しなくなりました

CSS ウェブページレイアウトを行う場合、XHTML1.0 仕様に準拠する必要があることは誰もが知っ...

HTML メタビューポート属性の詳細な説明

ビューポートとはモバイル ブラウザは、Web ページを仮想の「ウィンドウ」(ビューポート) に配置し...

MySQL 8.0.14 のインストールと設定方法のグラフィックチュートリアル

この記事では、MySQL 8.0.14のインストールと設定のプロセスを記録しています。具体的な内容は...

Linux viコマンドの知識ポイントと使い方のまとめ

Linux viコマンドの詳しい説明vi エディタは、すべての Unix および Linux システ...

LINUX でプロセスを表示する 4 つの方法 (要約)

プロセスは CPU とメモリ内で実行されるプログラム コードであり、各プロセスは 1 つ以上のプロセ...

HTML ウェブページのメタビューポート属性の説明

HTML メタビューポート属性の説明ビューポートとはモバイル ブラウザは、Web ページを仮想の「ウ...