MySQLでUPDATEクエリをバッチ処理する最も効率的な方法は何ですか?


10

大量の更新をデータベースに長期間フラッシュする必要があるアプリケーションを作成していますが、クエリを最適化する方法に行き詰まっています。現在私はを使用していますINSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE。これは、すべての値を1つのクエリにバッチ処理するように機能しますが、大きなテーブルでは非常に遅く実行されます。実際に行を挿入する必要はありません。

私が見た他のアプローチは、更新を使用SET value = CASE WHEN...することです(これはクエリを構築している方法のために生成するのが難しくCASE、数百/数千のキーのパフォーマンスについてはわかりません)、そして単に複数の連結アップデート。これらのどちらが私の現在の方法よりも速いでしょうか?

私の知る限り、MySQLでこれを行うための慣用的で効率的な方法はないことに戸惑います。よりも高速な方法がない場合ON DUPLICATE KEY、PostgreSQLに切り替えてそのUPDATE FROM構文を使用する価値はありますか?

他の提案も大歓迎です!

編集:頻繁に更新されるテーブルの1つを次に示します。無関係であるため、列名を削除しました。

CREATE TABLE IF NOT EXISTS `table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `a` bigint(20) unsigned NOT NULL DEFAULT '0',
  `b` bigint(20) unsigned NOT NULL DEFAULT '0',
  `c` enum('0','1','2') NOT NULL DEFAULT '0',
  `d` char(32) NOT NULL,
  -- trimmed --
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `c` (`c`),
  KEY `d` (`d`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

これは本番環境ではなくテストマシン上にあるため、InnoDBは完全に適切に調整されていません。INSERT FROMがどのように動作するかは完全にはわかりませんが、あなたの言ったことは正しいようです。質問をあなたが求めた情報で更新しました。
jli

回答:


14

InnoDBテーブルを使用しているため、最も明らかな最適化はUPDATE、複数のを1つのトランザクションにグループ化することです。

InnoDBトランザクションエンジンであること、あなただけのためではない支払うUPDATEそのものではなく、また、すべてのトランザクションのオーバーヘッド:、トランザクションバッファ、トランザクションログを管理するディスクにログをフラッシュします。

アイデアに論理的に慣れている場合はUPDATE、一度に100〜1000 秒をグループ化してみてください。

START TRANSACTION;
UPDATE ...
UPDATE ...
UPDATE ...
UPDATE ...
COMMIT;

考えられる欠点:

  • 1つのエラーがトランザクション全体を折りたたみます(ただし、コードで簡単に修正できます)
  • 1000 UPDATE秒が蓄積されるまで長い間待機する可能性があるため、タイムアウトを設定することもできます
  • アプリケーションコードがさらに複雑になります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.