sql >> データベース >  >> RDS >> Mysql

選択クエリへのMySqlの挿入は、1億行をコピーするには遅すぎます

    任意のINSERT ... SELECT ... クエリはSHAREDロックを取得します SELECTのソーステーブルから読み取る行。ただし、行の小さなチャンクを処理することで、ロックが長すぎることはありません。

    LIMIT ... OFFSETを使用したクエリ ソーステーブルを進むにつれて、だんだん遅くなります。チャンクあたり10,000行の場合、そのクエリを10,000回実行する必要があります。各行を最初からやり直してテーブルをスキャンし、新しいオフセットに到達する必要があります。

    何をしても、1億行のコピーには時間がかかります。たくさんの仕事をしています。

    pt-archiver を使用します 、この目的のために設計された無料のツール。 「チャンク」(またはサブセット)の行を処理します。各チャンクが0.5秒かかるように、チャンクのサイズを動的に調整します。

    メソッドとpt-archiverの最大の違いは、pt-archiverがLIMIT ... OFFSETを使用しないことです。 、主キーインデックスに沿って移動し、位置ではなく値で行のチャンクを選択します。したがって、すべてのチャンクがより効率的に読み取られます。

    コメントを再確認してください:

    バッチサイズを小さくし、反復回数を増やすと、パフォーマンスの問題が悪化すると予想されます。 、良くない。

    その理由は、LIMITを使用する場合です。 OFFSETを使用 、すべてのクエリはテーブルの先頭からやり直し、OFFSETまでの行をカウントする必要があります 価値。これは、テーブルを反復処理するにつれてますます長くなります。

    OFFSETを使用して20,000の高価なクエリを実行する 10,000の同様のクエリを実行するよりも時間がかかります。最もコストのかかる部分は、5,000行または10,000行を読み取ったり、宛先テーブルに挿入したりすることではありません。高価な部分は、最大50,000,000行を何度もスキップすることになります。

    代わりに、でテーブルを反復処理する必要があります オフセットではありません。

    INSERT IGNORE INTO Table2(id, field2, field3)
            SELECT f1, f2, f3
            FROM Table1
            WHERE id BETWEEN rowOffset AND rowOffset+limitSize;
    

    ループの前に、MIN(id)とMAX(id)を照会し、rowOffsetを開始します 最小値で、最大値までループします。

    これがpt-archiverの仕組みです。



    1. MySQL .. INSERT ... ON DUPLICATE KEY SELECTはありますか?

    2. 安全なTO_NUMBER()

    3. SQL Server SP-IN配列リストのパラメーターを渡しますか?

    4. MySQLで現在の日付を取得する方法