InnoDBテーブルからのスペースの削除と再利用


14

700GBのInnoDBテーブルがあり、それ以上データを書き込みません(読み取りのみ)。保持している古いデータを削除し、そのディスク領域を再利用します(不足しているため)。削除部分は非常に簡単です。auto-incプライマリインデックスがあるので、それを使用してチャンク単位で繰り返し、行を削除できますが、スペースを取り戻すことはできません。私はOPTIMIZE TABLEそう思いますが、700GBのテーブルではそれが永遠にかかるかもしれませんので、見落としている別のオプションはありますか?

RolandoMySQLDBAによる編集

テーブルがmydb.mytableであると仮定すると、次のクエリを実行してここに投稿し、テーブルの縮小に必要なディスク容量を判断できるようにしてください。

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

許可されている場合は、テーブル構造も確認する必要があります。

ノーム編集

これはクエリの出力です:

datsize ndxsize tblsize
682.51 47.57 730.08

これがテーブル構造です(SHOW CREATE TABLE

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

データのみをキャッチする別のディスクボリュームがありますか?
RolandoMySQLDBA 14

@RolandoMySQLDBAマウントできる外部ハードドライブがあります。それはカウントされますか?
ノーム14

@RolandoMySQLDBAだろうがのコース別の700ギガバイトを持ってすることなく、いくつかのスペースを削除するオプションのような
ノーム・

@RolandoMySQLDBAは、余分なディスクサイズがパフォーマンスの問題を引き起こしますか?
アリス

@Arisは、ディスクとそのシーク時間に依存します。最近では、ほとんどのディスクのパフォーマンスが向上していますが、テーブルに大きな空きスペースのディスクスペースがある場合、サイクルは無駄になります(非常に高速になります)。これは、通常16Kブロックに固定されているInnoDBに特に当てはまります。16Kブロックの内部断片化を使用して、ALTER TABLE ... ENGINE=InnoDB;(使用する余裕がある場合)を使用してテーブルを最適化することができます。ほとんどの人は非常に高速なSSDに満足しているだけで、心配する必要はありません。
-RolandoMySQLDBA

回答:


21

これはいい質問です。あなたはいくつかの解決策を持っていますが、あなたのテーブルは非常に大きいので、誰も痛みなしではありません:)

InnoDBテーブルを「縮小」するための3つのソリューションがあります。

1.テーブルの最適化

OPTIMIZE TABLE言及したinnodb_file_per_tableとおりに使用できますが、変数に注意する必要があります。

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

説明させてください:

OPTIMIZE TABLEInnoDBテーブルは、テーブルをロックwhithは、(結果は縮めている理由という)、元のテーブルを削除し、元の名前で新しいテーブルの名前を変更し、新しいクリーンなテーブルにデータをコピーします。そのため、テーブルの2倍のボリュームをディスクで使用できるようにする必要があります(操作中に2x700GBが必要になります)。

innodb_file_per_table = ONの場合。すべてのテーブルに適切なデータファイルがあります。そのため、OPTIMIZEステートメントは、操作が終了すると新しいデータファイル(〜700GB)を作成し、MySQLは元のファイルを削除し、新しいファイルの名前を変更します(したがって、データの700GB-おそらく縮小されるため、より少なくなります-)操作中に生成されたものは解放されます)

innodb_file_per_table = OFFにいるとき。すべてのデータは、1つのデータファイルに行く:ibdata。このファイルには悲しい特殊性があり、縮小することはできません。そのため、OPTIMIZEプロセス中に新しいテーブルが作成されます(700GB近く)が、ドロップおよび名前変更操作(およびOPTIMIZEフェーズの終了)後でも、ibdata〜700GBを解放しないため、一部のデータを解放したかったが、700GBもっと、かっこいいですね。

2. ALTER TABLE

ALTER TABLEステートメントを使用することもできます。これALTER TABLEはと同じように機能しOPTIMIZE TABLEます。あなただけを使用することができます:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLE(オンライン)

問題OPTIMIZEALTER TABLE、それが動作中にテーブルをロックしています。Perconaツールを使用できます:pt-online-schema-change(Percona Toolkitから:link )。pt-online-schema ...は、トリガーと一時テーブルを使用してメカニズムを構築し、操作中に元のテーブルを読み書きできるようにします。私はこのツールを本番環境で使用していますALTER

FOREIGN KEYテーブル、FKを参照し、混乱を引き起こすリスクをトリガーする必要があることに注意してください。この前提条件を確認するには、次のクエリを実行します。

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

pt-online-schema-changeの使用方法は次のとおりです。

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

innodb_file_per_tableに関する私のメモは、このソリューションでも当てはまることに注意してください。

4. mysqldump

最後の解決策は、ダンプからすべてのデータベースを再作成することです。非常に長いですが、非常に効率的です。ibdataファイルを「縮小」する唯一のソリューションであることに注意してください。

最大


また、perconaツールのオンライン変更テーブルオプションでは、700GBの空きディスク容量が必要ですか?
ノーム14

はい、pt-onlineはALTERをオンラインで行うために何らかのメカニズムを使用していますが、とにかくALTERを作成します。
マキシムFouilleul 14

@MaximeFouilleulは、追加のディスクサイズによってパフォーマンスの問題が発生しますか?
アリス

1

ディスクサイズが不足している場合、Maxがpt-online-schema-change(ONLINE)で提案したのと同じようにすることをお勧めします。私はずっと小さなテーブル(200GB)で同じ状況にあり、同時にいくつかの圧縮を行うことを選択しました。これに沿った何かが動作するはずです:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

これは、テーブルのbarracudaファイル形式およびCOMPACT形式の場合にのみ機能します。また、innodb_file_per_tableを有効にする必要があります。これは、特に大量のテキストがあり、8Kまたは4K(デフォルトは16K)などの小さいKEY_BLOCK_SIZEを使用している場合、テーブルのサイズに驚異的です。また、他のブログでこの問題に関する複数のベンチマークからどれだけのスペースを獲得できるかを確認することもできますが、MySQLのドキュメントは25%から50%を宣伝しています(私にとってはほぼ90%でした)。

これは、SELECTを実行するときのパフォーマンスにも影響する可能性があることに注意してください(MySQLドキュメントから)。

したがって、バッファプールには、圧縮されたページと圧縮されていないページの両方が含まれている場合もあれば、圧縮されたページのみが含まれている場合もあります。

MySQLは、バッファプールにないときにデータを解凍する必要もあります。だから注意してください。

私の場合、これは本当にうまくいきました。長いテキストがありました。200GBは26GBになりました。パフォーマンスは変更されていません。

詳細については、これらのリンクを確認してください。

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.