検証dbを作成する際のデータマスキングで、
1000万レコードに対して一括UPDATEを行うことがあったが、1時間ほどかかった。
以下の①,②を考える。
①なぜここまで遅くなるのか
②どうすれば早くなるのか
実行したSQL
update users
set name = 'ダミー'
調査
以下の記事にUPDATE文を実行すると起きることがわかりやすくまとめられていた。
引用
RDBMSはSQL文1を受け取ると,SELECT文を受け取った時と同じように構文解析を行います。そして,UPDATE文であることを理解します。続いて,UPDATE対象のレコードを探します。このレコードを探す方法は,SELECT文と同じです。まず,「メモリー・バッファ」内に対象のレコードが存在していないかを確認し,存在していない場合は,ディスク上の「データベース・ファイル」から読み込みます。そして,メモリー・バッファ内に読み込んだ対象のレコードの値を指定された値に更新します。
つまり、updateの時
メモリにはupdate対象のレコードが展開され、さらにその更新後の値も保持する。
①
上記のようなことが、1000万レコードに対して実行された際簡単にメモリが溢れて、
スワップが起きてしまい遅くなってしまっていたよう。
②
①の原因を考えると、単純に一回にメモリに乗せる量を減らせばいいと推測できる。
以下の様に10回のupdateに分けた。
実行時間は、
一回あたり40秒 * 10 = 6分40秒
だいぶ早くなった。
ストアドプロシージャなどを使ってもう少し実行しやすい形にしたい。。
update users
set name = 'ダミー'
where between 1 AND 1000000;
update users
set name = 'ダミー'
where between 1000001 AND 2000000;
・
・
・
update users
set name = 'ダミー'
where between 9000001 AND 10000000;