InnoDBテーブルから断片化をどのように削除しますか?


13

複数のテーブルを持つデータベースがあります。

レコードの数が20Kまたは50Kを超えていると言うテーブルからいくつかのレコードを削除したい。

すべてのテーブルはInnoDBです。そして、file_per_tableあるオフ

いくつかのテーブルからレコードを削除すると、テーブルに断片化が生じます。

断片化を削除する方法はありますか?

4月17日に更新

mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME      | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City            | world_innodb |   5242880 |
| City_Copy       | world_innodb |   5242880 |
| Country         | world_innodb |   5242880 |
| CountryLanguage | world_innodb |   5242880 |
| a               | world_innodb |   5242880 |
| t1              | world_innodb |   5242880 |
| t2              | world_innodb |   5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)

だから今私の質問は、私のテーブルが断片化されているかどうかをどのように決定するかということです。



1
また、InnoDBの記事 Perconaのブログサイトからの断片化に注意してください。
ypercubeᵀᴹ

回答:


14

これについては、2010年10月にStackOverflowで取り上げました

InnoDBインフラストラクチャで最も忙しいファイル:/ var / lib / mysql / ibdata1に注意してください

このファイルには通常、4種類の情報が含まれています

  • テーブルデータ
  • テーブルインデックス
  • MVCC(マルチバージョン同時実行制御)データ
  • テーブルメタデータ(テーブルスペースIDのリスト)

OPTIMIZE TABLEibdata1に保存されているInnoDBテーブルに対して実行すると、次の2つのことが行われます。

  • テーブルのデータとインデックスをibdata1内で連続させ、アクセスを高速化します
  • 連続したデータおよびインデックスページがibdata1に追加されるため、ibdata1が成長します。

テーブルデータとテーブルインデックスをibdata1から分離し、innodb_file_per_tableを使用して個別に管理することができますが、ibdata1のディスクスペースの大きなギャップ全体は単純に消えず、回収できません。あなたはもっとしなければなりません。

するために、一度、すべてのibdata1とをシュリンクあなたは、次の操作を行う必要があります。

1)MySQLDumpすべてのデータベースをSQLテキストファイル(/root/SQLData.sqlと呼びます)

2)すべてのデータベースを削除します(mysqlスキーマを除く)

3)mysqlのシャットダウン

4)/etc/my.cnfに次の行を追加します

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

サイドノート:innodb_buffer_pool_sizeの設定にかかわらず、innodb_log_file_sizeがinnodb_buffer_pool_sizeの25%であることを確認してください。

5)ibdata1、ib_logfile0、およびib_logfile1を削除します

この時点では、/ var / lib / mysqlにのみmysqlスキーマが存在するはずです。

6)mysqlを再起動します

これにより、10MBまたは18MB(MySQLのバージョンに応じて)でibdata1、それぞれ1Gでib_logfile0およびib_logfile1が再作成されます

7)/root/SQLData.sqlをmysqlにリロードします

ibdata1は成長しますが、テーブルメタデータのみが含まれます。実際、それは何年もかけて非常にゆっくりと成長します。ibdata1を迅速に成長させる唯一の方法は、次の1つ以上がある場合です。

  • DDLの多く(CREATE TABLEDROP TABLEALTER TABLE
  • 多くのトランザクション
  • トランザクションごとにコミットする多くの変更

各InnoDBテーブルはibdata1の外部に存在します

mydb.mytableという名前のInnoDBテーブルがあるとします。/ var / lib / mysql / mydbに移動すると、テーブルを表す2つのファイルが表示されます

  • mytable.frm(ストレージエンジンヘッダー)
  • mytable.ibd(mydb.mytableのテーブルデータとテーブルインデックスのホーム)

ibdata1にはInnoDBデータとインデックスが含まれなくなります。

/etc/my.cnfのinnodb_file_per_tableオプションを使用するOPTIMIZE TABLE mydb.mytable;と、実行でき、ファイル/var/lib/mysql/mydb/mytable.ibdが実際に縮小します。

私はMySQL DBAとしてのキャリアの中でこれを何度もやりました

実際、初めてこれを行ったとき、50GBのibdata1ファイルを500MBに縮小しました。

試してみる。これについてさらに質問がある場合は、私にメールしてください。私を信じて。これは短期的にも長期的にも機能します!!!

更新2012-04-19 09:23 EDT

上記の手順を実行した後、どのテーブルを最適化する必要があるかをどのように判断できますか?見つけることは可能ですが、スクリプトを作成する必要があります。

例は次のとおりmydb.mytableです。テーブルがあるとします。innodb_file_per_tableを有効にすると、ファイル/var/lib/mysql/mydb/mytable.ibdができます

2つの番号を取得する必要があります

OSからのファイルサイズ:このようにOSからファイルサイズを確認できます

ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'

INFORMATION_SCHEMAからのFILESIZE:次のようにinformation_schema.tablesからファイルサイズを確認できます。

SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

OS値からINFORMATION_SCHEMA値を減算し、その差をINFORMATION_SCHEMA値で除算するだけです。

そこから、そのテーブルを最適化する必要があると考える割合を決定します。もちろん、次のコマンドのいずれかを使用してデフラグします。

OPTIMIZE TABLE mydb.mytable;

または

ALTER TABLE mydb.mytable ENGINE=InnoDB;

推奨されるinnodb_file_per_table = 1オプションを使用している場合、/ var / lib / mysql / ibdata1が非常に忙しいとは思わない
-CrackerJack9

1
@ CrackerJack9 ibdata1は、1)ダブルバッファ情報の書き込み、2)セカンダリインデックスのバッファの挿入、3)データディクショナリ、4)セグメントのロールバック、5)テーブルスペースの取り消しのため、信じられないほどスーパービジーです。これらの図の説明については、scribd.com / doc / 31337494 / XtraDB-InnoDB-internals-in-drawingにアクセスしてください。InnoDBテーブルのデータおよびインデックスページを削除しても、高トランザクション環境ではibdata1が大幅に増加する可能性があります。
-RolandoMySQLDBA

1
@ CrackerJack9私はibdata1の周りの追加アクティビティについて議論する追加の投稿があります:dba.stackexchange.com/a/23367/877-RolandoMySQLDBA
1

私はそれがまだそれほど頻繁に使用されていることに気付いていませんでした。ありがたい!
CrackerJack9

@RolandoMySQLDBA時間があるときにヒープをポップできますか?
ypercubeᵀᴹ

5

行を頻繁に削除する(または可変長データ型で行を更新する)と、ファイルシステムの断片化と同様に、データファイルに多くの無駄なスペースが生じる可能性があります。

このinnodb_file_per_tableオプションを使用していない場合、できることは、データベースのエクスポートとインポート、つまり時間とディスクを大量に消費する手順だけです。

ただし、を使用している場合はinnodb_file_per_table、このスペースを特定して再生できます。

5.1.21より前のリリースでは、information_schema.tablesのtable_comment列から空き領域カウンターを使用できます。以下に、少なくとも100M(実際には97.65M)の空き領域があるテーブルを識別するSQLを示します。

SELECT table_schema、table_name、table_comment FROM
information_schema.tables WHERE ENGINE LIKE 'InnoDB' AND table_comment RLIKE 'InnoDB free:([0-9] {6、})。*';

5.1.21以降、これはdata_free列に移動されました(はるかに適切な場所)。

SELECT table_schema、table_name、data_free / 1024/1024 AS data_free_MB FROM information_schema.tables WHERE ENGINE LIKE 'InnoDB' AND data_free> 100 * 1024 * 1024;

テーブルを再構築することにより、失われたスペースを再利用できます。これを行う最良の方法は、実際には何も変更せずに「alter table」を使用することです。

ALTER TABLE `TableName` ENGINE=InnoDB;

これは、InnoDBテーブルで「テーブルの最適化」を実行した場合にMySQLがバックグラウンドで実行することです。その結果、読み取りロックが発生しますが、完全なテーブルロックは発生しません。所要時間は、テーブル内のデータ量に完全に依存します(データファイルのサイズではありません)。大量の削除または更新があるテーブルがある場合、これを毎月、または毎週実行することもできます。


もう1つは、data_freeの意味がわからない> 100 * 1024 * 1024 ..そして結果を見たときに、テーブルが断片化されているかどうかを判断できない.. ??テーブルが断片化されている、または断片化されていないと言うことができます。
アブドゥルマナフ

更新部分をご覧ください。
アブドゥルマナフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.