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の動作原理を分析する

推薦する

HTML でフレームセット タグを使用するチュートリアル

フレームセット ページは通常の Web ページとは多少異なります。依然として <HTML>...

HTMLタグと基本要素の学習のまとめ

1. HTML の要素とタグ<br />要素は、1 つのタグまたは 1 組のタグによって...

Vue で Axios カプセル化を使用するための完全なチュートリアル

序文現在、プロジェクトでは、Axios ライブラリが HTTP インターフェース リクエストによく使...

MySQL ビューの原則分析

目次更新可能なビュービューのパフォーマンスビューの制限ビューは MySQL 5.0 以降で導入されま...

フロントエンドの上級者向けコースでは、JavaScript のストレージ機能の使い方を学習します。

目次序文背景実施計画の考え方js ストレージ機能ソリューション設計やっと要約する序文どの SaaS ...

js でショッピングモールのシミュレーションを実現

HTML、CSS、JSフロントエンドを学習中の皆さん、今回はショッピングモールの事例の実装をシェアし...

スクロールバーのスタイルを設定するための CSS サンプルコード

スクロール バーのスタイルを設定するための CSS 実装コードは次のとおりです。 •::-webki...

Docker で Maven プロジェクトをより速くビルドする

目次I. 概要2. 従来の多段階イメージ構築3. Buildkitを使用してイメージをビルドする4....

MySQLクエリ文の実行プロセスの詳細な説明

目次1. クライアントとサーバー間の通信方法2. クエリキャッシュ3. クエリ最適化処理4. クエリ...

動的および静的分離を実現する nginx のサンプルコード

1. nginxの動的と静的の分離の簡単な設定web1は静的サーバー、web2は動的サーバー、nod...

ウェブページの読み込み速度を上げる6つのヒント

第二に、キーワードのランキングは、Webページの表示速度にも関係しています(参照:キーワードランキン...

Linux に Python クローラー スクリプトを展開し、スケジュールされたタスクを設定する方法

昨年、プロジェクトの必要性により、Python でクローラーを作成しました。クロールされたデータは、...

77.9K の GitHub リポジトリを持つ Axios プロジェクト: 学ぶ価値のあることは何でしょうか?

目次序文1. Axiosの紹介2. HTTPインターセプターの設計と実装2.1 インターセプターの紹...

Vue 計算プロパティ実装トランスクリプト

この記事では、Vueの計算プロパティ実装レポートカードを参考に共有します。具体的な内容は次のとおりで...

MySQLのストレージエンジンについてお話しましょう

基礎リレーショナル データベースでは、各データ テーブルはファイルに相当し、異なるストレージ エンジ...