4

MYISAM テーブルで構成された DB スキーマがあります。いくつかのテーブルから古いレコードを時々削除したいと考えています。

削除はメモリ領域を再利用しないことは知っていますが、DELETE コマンドの説明でわかったように、挿入は削除された領域を再利用する可能性があります

MyISAM テーブルでは、削除された行はリンクされたリストに保持され、後続の INSERT 操作は古い行の位置を再利用します。

LOAD DATA コマンドも削除されたスペースを再利用するかどうかに興味がありますか?

アップデート

また、インデックス スペースがどのように再利用されたのかにも興味があります。

更新 2012-12-03 23:11

@RolandoMySQLDBA から受け取った回答に基づいて提供される追加情報

次の推奨クエリを実行した後、スペースを再利用または再利用する必要があるテーブルごとに異なる結果が得られました。

SELECT row_format FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable1';

>Dynamic

SELECT row_format FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable2';

>Fixed

更新 2012-12-09 08:06

LOAD DATA行フォーマットが固​​定されている場合、または(行フォーマットが動的で、まったく同じサイズの削除された行がある)場合にのみ、以前に削除されたスペースを再利用します(短いスクリプトを実行して確認しました)。

row_format が動的である場合、削除されたリストの完全なルックアップが各レコードに対して行われ、正確な行サイズが見つからない場合、削除されたレコードは使用されず、テーブルのメモリ使用量が増加し、LOAD DATAさらにレコードのインポートにはるかに時間がかかります。

すべてのプロセスを完全に説明しているため、ここでの回答は除外します。

4

1 に答える 1

5

という名前の MySQL テーブルの場合はmydb.mytable、次を実行します。

OPTIMIZE TABLE mydb.mytable;

これを段階的に行うこともできます。

CREATE TABLE mydb.mytable_new LIKE mydb.mytable;
ALTER TABLE mydb.mytable_new DISABLE KEYS;
INSERT INTO mydb.mytable_new SELECT * FROM mydb.mytable;
ALTER TABLE mydb.mytable_new ENABLE KEYS;
ALTER TABLE mydb.mytable RENAME mydb.mytable_old;
ALTER TABLE mydb.mytable_new RENAME mydb.mytable;
ALTER TABLE mydb.mytable_old;
ANALYZE TABLE mydb.mytable;

いずれの場合も、テーブルは断片化されずに終了します。

試してみる !!!

更新 2012 年 12 月 3 日 12:50 EDT

を介した一括 INSERT で行が再利用されるかどうかが気になる場合はLOAD DATA INFILE、次の点に注意してください。

MyISAM テーブルを作成したとき、デフォルトの行形式は動的であると想定しました。どちらかでそれが何であるかを確認できます

SHOW CREATE TABLE mydb.mytable\G

また

SELECT row_format FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

テーブルの行形式はDynamicであるため、断片化された行のサイズはさまざまです。MyISAM ストレージ エンジンは、挿入される次のデータ セットが収まるかどうかを確認するために、削除された各行の長さをチェックし続けます。着信データが削除されたどの行にも収まらない場合は、新しい行データが追加されます。

そのような行の存在はmyisamchk苦労する可能性があります。

これが、実行を推奨する理由ですOPTIMIZE TABLE。そうすれば、データはより速く追加されます。

更新 2012-12-03 12:58 EDT

これはあなたができる興味深いことです: concurrent_insert を 2 に設定してみてください。そうすれば、テーブルのギャップをチェックせずに、常に MyISAM テーブルに追加できます。これにより、INSERT が劇的に高速化されますが、既知のギャップはすべてそのままになります。

を使用して、できるだけ早くテーブルをデフラグすることもできますOPTIMIZE TABLE

更新 2012 年 12 月 3 日 13:40 EDT

2 番目の提案を実行しないでください

CREATE TABLE mydb.mytable_new LIKE mydb.mytable;
ALTER TABLE mydb.mytable_new DISABLE KEYS;
INSERT INTO mydb.mytable_new SELECT * FROM mydb.mytable;
ALTER TABLE mydb.mytable_new ENABLE KEYS;
ALTER TABLE mydb.mytable RENAME mydb.mytable_old;
ALTER TABLE mydb.mytable_new RENAME mydb.mytable;
ANALYZE TABLE mydb.mytable;

これはあなたにアイデアを与えるでしょう

  • OPTIMIZE TABLE実行にかかる時間
  • 実行後に.MYDとがどれだけ小さくなるか.MYIOPTIMIZE TABLE

私の2番目の提案を実行した後、それらを比較できます

SELECT
    A.mydsize,B.mydsize,A.mydsize - B.mydsize myd_diff,
    A.midsize,B.myisize,A.myisize - B.myisize myi_diff
FROM
(
    SELECT data_length mydsize,index_length myisize
    FROM information_schema.tables
    WHERE table_schema='mydb' AND table_name='mytable'
) A,
(
    SELECT data_length mydsize,index_length myisize
    FROM information_schema.tables
    WHERE table_schema='mydb' AND table_name='mytable_new'
) B;

更新 2012-12-03 16:42 EDT

ROW_FORMAT が固定に設定されているテーブルには、毎回同じ長さの行を割り当てる余裕があります。MyISAM テーブルが削除された行のリストを保持している場合、リストの最初の行は、データを挿入する次の行として常に選択する必要があります。十分な長さの適切な行ギャップが見つかるまで、リスト全体をトラバースする必要はありません。削除された各行は、DELETE. 各 INSERT は、削除された行の最初の行を選択します。

MyISAM テーブルは同時挿入を実行できるため、これらのことを想定できます。この機能をconcurrent_insertオプションで利用できるようにするには、MyISAM テーブルへの INSERT で次の 3 つのうちの 1 つを検出できる必要があります。

  1. 削除された行のリストの存在、したがってリストからの選択
    • Row_Format=Dynamic : 各行の長さが異なる削除された行のリスト
    • Row_Format=Fixed : すべての行が同じ長さの削除された行のリスト
  2. 削除された行のリストがないため、追加されます
  3. 削除された行のリストの存在チェックをバイパスします ( concurrent_insertを 2 に設定)

検出 #1 を可能な限り高速にするには、MyISAM テーブルの row_format を Fixed にする必要があります。動的な場合は、リストのトラバーサルが必要になる可能性が非常に高くなります。

于 2012-12-03T17:07:37.823 に答える