20秒ごとにCSVを読み取る必要があります。各CSVには最小値が含まれます。500から最大 60000行。Postgresテーブルにデータを挿入する必要がありますが、重複するアイテムを取得する可能性が高いため、その前にアイテムがすでに挿入されているかどうかを確認する必要があります。一意性をチェックするフィールドにもインデックスが付けられます。
そのため、ファイルをチャンクで読み取り、IN句を使用して、データベースに既に存在するアイテムを取得します。
それを行うためのより良い方法はありますか?
20秒ごとにCSVを読み取る必要があります。各CSVには最小値が含まれます。500から最大 60000行。Postgresテーブルにデータを挿入する必要がありますが、重複するアイテムを取得する可能性が高いため、その前にアイテムがすでに挿入されているかどうかを確認する必要があります。一意性をチェックするフィールドにもインデックスが付けられます。
そのため、ファイルをチャンクで読み取り、IN句を使用して、データベースに既に存在するアイテムを取得します。
それを行うためのより良い方法はありますか?
これはうまく機能するはずです:
CREATE TEMP TABLE tmp AS SELECT * FROM tbl LIMIT 0 -- copy layout, but no data
COPY tmp FROM '/absolute/path/to/file' FORMAT csv;
INSERT INTO tbl
SELECT tmp.*
FROM tmp
LEFT JOIN tbl USING (tbl_id)
WHERE tbl.tbl_id IS NULL;
DROP TABLE tmp; -- else dropped at end of session automatically
この答えと密接に関連しています。
まず、完全を期すために、Erwinのコードを使用するように変更しましたexcept
CREATE TEMP TABLE tmp AS SELECT * FROM tbl LIMIT 0 -- copy layout, but no data
COPY tmp FROM '/absolute/path/to/file' FORMAT csv;
INSERT INTO tbl
SELECT tmp.*
FROM tmp
except
select *
from tbl
DROP TABLE tmp;
それから私はそれを自分でテストすることを決心しました。9.1でほとんど手つかずでテストしましたpostgresql.conf。ターゲットテーブルには1,000万行、オリジンテーブルには3万行が含まれています。ターゲットテーブルにはすでに15,000が存在します。
create table tbl (id integer primary key)
;
insert into tbl
select generate_series(1, 10000000)
;
create temp table tmp as select * from tbl limit 0
;
insert into tmp
select generate_series(9985000, 10015000)
;
厳選された部分のみの説明をお願いしました。exceptバージョン:
explain
select *
from tmp
except
select *
from tbl
;
QUERY PLAN
----------------------------------------------------------------------------------------
HashSetOp Except (cost=0.00..270098.68 rows=200 width=4)
-> Append (cost=0.00..245018.94 rows=10031897 width=4)
-> Subquery Scan on "*SELECT* 1" (cost=0.00..771.40 rows=31920 width=4)
-> Seq Scan on tmp (cost=0.00..452.20 rows=31920 width=4)
-> Subquery Scan on "*SELECT* 2" (cost=0.00..244247.54 rows=9999977 width=4)
-> Seq Scan on tbl (cost=0.00..144247.77 rows=9999977 width=4)
(6 rows)
outer joinバージョン:
explain
select *
from
tmp
left join
tbl using (id)
where tbl.id is null
;
QUERY PLAN
--------------------------------------------------------------------------
Nested Loop Anti Join (cost=0.00..208142.58 rows=15960 width=4)
-> Seq Scan on tmp (cost=0.00..452.20 rows=31920 width=4)
-> Index Scan using tbl_pkey on tbl (cost=0.00..7.80 rows=1 width=4)
Index Cond: (tmp.id = id)
(4 rows)