データベースサーバー(あなたの場合のように)のレイテンシーが非常に悪い場合でも、トリックを使用して一括更新操作を高速化できます。テーブルを直接更新する代わりに、ステージテーブルを使用します 新しいデータを非常に高速に挿入するには、 destination-tableに対して1回のjoin-updateを実行します。 。これには、データベースに送信する必要のあるステートメントの数を大幅に減らすという利点もあります。
これはUPDATEでどのように機能しますか?
テーブルentries
があるとします 常に新しいデータが届いていますが、更新したいのはすでに保存されているデータだけです。宛先テーブルentries_stage
のコピーを作成します 関連するフィールドのみが含まれています:
entries = Table('entries', metadata,
Column('id', Integer, autoincrement=True, primary_key=True),
Column('value', Unicode(64), nullable=False),
)
entries_stage = Table('entries_stage', metadata,
Column('id', Integer, autoincrement=False, unique=True),
Column('value', Unicode(64), nullable=False),
)
次に、一括挿入を使用してデータを挿入します。これは、SQLAlchemyでネイティブにサポートされていないが、それほど問題なく構築できるMySQLの複数値挿入構文を使用する場合にさらに高速化できます。
INSERT INTO enries_stage (`id`, `value`)
VALUES
(1, 'string1'), (2, 'string2'), (3, 'string3'), ...;
最後に、次のように、destination-tableの値をstage-tableの値で更新します。
UPDATE entries e
JOIN entries_stage es ON e.id = es.id
SET e.value = es.value;
これで完了です。
インサートはどうですか?
もちろん、これはインサートを高速化するためにも機能します。すでにステージテーブルにデータがあるので 、あなたがする必要があるのはINSERT INTO ... SELECT
を発行することだけです destination-tableにないデータを含むステートメント まだ。
INSERT INTO entries (id, value)
SELECT FROM entries_stage es
LEFT JOIN entries e ON e.id = es.id
HAVING e.id IS NULL;
これの良いところは、INSERT IGNORE
を実行する必要がないことです。 、REPLACE
またはON DUPLICATE KEY UPDATE
、何もしない場合でも主キーをインクリメントします 。