こんにちは、なかわけです。
いまpostgresのlargeobjectを大量にコピーする作業をしています。
元のデータベースに3000万行くらいあってそれをまるっとそっくりコピーのデータベースに流し込みます。
INSERT INTO pg_largeobject SELECT * FROM dblink('dbname=元データベース', SELECT * FROM pg_largeobject') AS t1 (loid oid, pageno integer, data bytea);
最初一回でコピーしようとしたらメモリエラーで失敗しました。そりゃそうですよねw
それで3000万行を10万行ずつに分割して書いたクエリのテキストファイルを読み込ませて
データを流し込むことにしました。たとえば、以下はその中のひとつのクエリ。
INSERT INTO pg_largeobject SELECT * FROM dblink( 'dbname=元データベース', 'SELECT * FROM pg_largeobject ORDER BY loid, pageno LIMIT 100000 OFFSET 200000') AS t1(loid oid,pageno integer,data bytea);
始めの方は10万行を挿入するのに1、2分程度で処理されていましたが、だんだん処理が遅くなり、
1000万行を挿入し終わったあたりでは10万行挿入するのに15分程度かかるようになってしまいました。
時間がかかってしょうがないです。どうしたものか。
ところが、とあるところからいい方法を教えてもらいました。
INSERT INTO pg_largeobject SELECT * FROM dblink( 'dbname=元データベース', 'SELECT * FROM pg_largeobject WHERE loid BETWEEN n AND m') AS t1(loid oid,pageno integer,data bytea);
ORDERしてLIMIT、OFFSETするのではなく、BETWEENを使うんですね!
確かにこっちの方が処理が少ない分早そうだし、実際めちゃ早かったです。
あーよかったよかった!