web-dev-qa-db-ja.com

復元後の異なるMySQLデータファイルサイズ

私はデータベース管理の新人です。現在の会社のデータベースアーキテクチャは、マスタースレーブレプリケーションです。 MySQLバージョン5.0.86を使用しています。

数週間前、会社のメインアプリをアップグレードしました。このアップグレードにより、データベースのすべてのテーブルに列が追加されました。アップグレード前は、ibdataのサイズは約3.1GiBでした。アップグレード後は、約5.2GiBです。

今日、私はmysqldumpで完全なバックアップと復元のテストを行いました。復元後、ibdataのサイズは約3.6 GiBです。標準の選択では、復元時に元のデータベースと同じデータが表示されます。

Select to information_schemaでデータサイズを確認しました(CUSTODIAはメインアプリの名前です)。

select SUM(DATA_LENGTH+INDEX_LENGTH) from TABLES where TABLE_SCHEMA='CUSTODIA';

これはマスターデータベースの結果です:

+-------------------------------+
| SUM(DATA_LENGTH+INDEX_LENGTH) |
+-------------------------------+
|                    5683345068 |
+-------------------------------+

これは復元されたデータベースの結果です:

+-------------------------------+
| SUM(DATA_LENGTH+INDEX_LENGTH) |
+-------------------------------+
|                    3735748608 |
+-------------------------------+

私の質問:

  1. 元のデータベースと復元されたデータベースのサイズにこの違いがあるのはなぜですか?
  2. このサイズの違いはあるものの、復元されたデータベースに問題がないと想定しても安全ですか?
  3. MySQLはどのようにdata_lengthを計算しますか?見積もりですか?
  4. ダウンタイムなしで、プロダクションのibdataファイルサイズを安全に3.6GiBに縮小できますか?

これについてのご意見をいただければ幸いです。ありがとうございました。

5
juanman80

これは私にとって世界のすべての理にかなっています。

InnoDBは、それぞれ16Kのデータページとインデックスページを作成します 。データの行が挿入、更新、削除、コミット、およびロールバックされている場合、断片化が発生します!!!

内部フラグメンテーションが発生する可能性のあるケースは2つあります。

  • 特定の列の値によって行が大きくなりすぎてデータページに収まらないため、1つの行が複数のデータページに書き込まれる可能性があります。
  • 32Kのデータを含むTEXT列があります。

これらの2つのケースでは、複数のデータページにまたがる単一の行をリンクリストのようにチェーンする必要があります。内部で生成されたデータページのリストは、行が読み取られるときに常にナビゲートする必要があります。

クレジットの期限が到来するところでクレジットを与えると、PostgreSQLは TOAST(オーバーサイズ属性ストレージテクニック) と呼ばれる非常に優れたメカニズムを実装して、この種の内部断片化の波を食い止めるためにテーブルの外にオーバーサイズデータを保持しました。

Mysqldumpを使用してCREATE TABLEステートメントでファイルを作成し、その後に多数のINSERTを実行すると、mysqldumpを新しいサーバーにロードするときに、未使用のスペースのない新しいテーブルと連続したデータおよびインデックスページが得られます。

私の説明では、userinfoというCUSTODIAデータベースにInnoDBテーブルがあると仮定しましょう

テーブルを圧縮する場合は、3つのオプションがあります。

オプション1

OPTIMIZE TABLE CUSTODIA.userinfo;

オプション2

ALTER TABLE CUSTODIA.userinfo ENGINE=InnoDB;

オプション3

CREATE TABLE CUSTODIA.userinfo2 LIKE CUSTODIA.userinfo;
INSERT INTO CUSTODIA.userinfo2 SELECT * FROM CUSTODIA.userinfo;
DROP TABLE CUSTODIA.userinfo;
ALTER TABLE CUSTODIA.userinfo2 RENAME CUSTODIA.userinfo;

警告:オプション3は、制約のあるテーブルでは適切ではありません。オプション3はMyISAMに最適です。

今あなたの質問のために:

質問1.元のデータベースと復元されたデータベースのサイズにこの違いがあるのはなぜですか?

上記で説明したように

質問2.このサイズの違いはありますが、復元されたデータベースは問題ないと想定しても安全ですか?

両方のサーバーのデータがまったく同じであることを確実にしたい場合は、両方のDBサーバーで次のコマンドを実行します。

CHECKSUM TABLE CUSTODIA.userinfo;

うまくいけば、チェックサム値は両方のサーバーの同じテーブルで同一です。数十、さらには数百のテーブルがある場合は、それをスクリプト化する必要があります。

質問3:MySQLはどのようにdata_lengthを計算しますか?見積もりですか?

Data_lengthとindex_lengthの合計に正しい方法を使用しています。私の断片化の説明に基づくと、これは推定値です。

質問4.プロダクションのibdataファイルのサイズをダウンタイムなしで3.6GiBまで安全に削減できますか?

良いニュース!!!絶対に圧縮できます!!!実際、それをその数の分数にどのように圧縮したいですか??? StackOverflow および ServerFault でこの問題に対処したため、これらの2つのリンクをたどってください。

https://stackoverflow.com/questions/3927690/howto-clean-a-mysql-innodb-storage-engine/4056261#4056261

https://serverfault.com/questions/230551/mysql-innodb-innodb-file-per-table-cons/231400#2314

悪いニュース !!!申し訳ありませんが、ib_logfile0とib_logfile1を再構築し、ibdata1を一度に縮小するために、3〜5分のダウンタイムウィンドウがあります。これは1回限りの操作になるため、価値があります。

5
RolandoMySQLDBA

Q3-ディスクのフットプリントについて質問していますか?またはデータサイズ?サイズは、使用されるディスク領域の正確なサイズです。データとインデックスの大きさの過大評価があります-なぜなら

  • 16KBブロックはめったにいっぱいにならない

  • 767Bより大きいフィールドは、1MB単位(またはそのようなもの)で割り当てられている他の領域に振り分けられます。

  • テーブルが通常のサイズよりも大きくなると、8MBのエクステントが追加され、その一部は「空き」のままになります。

  • PRIMARY KEY順序で挿入すると、dataブロックが適度に密にパックされたままになります。それ以外の場合、データおよびインデックスブロックは、ロードプロセス中にランダムな挿入とブロック分割の気まぐれになります。ランダムに挿入すると、ブロック分割のランダムな性質のため、ブロックが約69%使用されます。

  • InnoDBはインデックスの更新を遅らせようとするため、先ほど説明した混乱を減らすことができます。ただし、テーブルがinnodb_buffer_pool_sizeよりもはるかに大きい場合、この最適化の実行量には制限があります。

上記のすべての要因により、リロードによりディスクフットプリントが大きくなったり、小さくなったりする場合があります。

1行のテーブルのavg_row_lengthが16KBであることに気付いたことがありますか?

1
Rick James