2

500 万を超えるエントリを含む Postgre SQL データベース テーブルがあります。100,000 エントリを含む CSV ファイルもあります。

CSV ファイルのデータに関連する DB からデータを取得するには、クエリを実行する必要があります。

しかし、皆さんの理解と私自身の経験によると、この種のクエリは完了するまでに時間がかかります。(私の推測では6時間以上)

最新の調査結果とツールによると、これと同じタスクを実行するためのより優れた高速なソリューションはありますか?

4

3 に答える 3

6

高速レーン: CSV ファイルの構造に一致する一時テーブルを作成し(便宜上、既存のテーブルをテンプレートとして使用する可能性があります)、次を使用しますCOPY

バルクロード

CREATE TEMP TABLE tmp(email text);

COPY tmp FROM 'path/to/file.csv';
ANALYZE tmp;                       -- do that for bigger tables!

CSV 内のメールは一意であると想定していますが、指定していません。そうでない場合は、一意にます。

CREATE TEMP TABLE tmp0
SELECT DISTINCT email
FROM   tmp
ORDER  BY email;  -- ORDER BY cheap in combination with DISTINCT ..
                  -- .. may or may not improve performance additionally.

DROP TABLE tmp;
ALTER TABLE tmp0 RENAME TO tmp;

索引

あなたの特定のケースでは、電子メールの一意のインデックスが適切です。データをロードしてサニタイズしたにインデックスを作成する方がはるかに効率的です。このようにCOPYして、重複があった場合に一意の違反で救済することも防ぎます。

CREATE UNIQUE INDEX tmp_email_idx ON tmp (email);

よく考えてみると、大きなテーブルを更新するだけなら、一時テーブルにインデックスはまったく必要ありません。順次読まれます。

はい DB テーブルは主キーを使用して索引付けされます。

この場合の唯一の関連インデックス:

CREATE INDEX tbl_email_idx ON tbl (email);

CREATE UNIQUE INDEX ...できれば作ってください。

アップデート

後のコメントで詳しく説明されているようにテーブルを更新するには:

UPDATE tbl t
SET    ...
FROM   tmp 
WHERE  t.email = tmp.email;

これらはすべて、plpgsql または sql 関数に簡単にラップできます。ファイル名をパラメータ化する場合は、plpgsql 関数で動的 SQL を使用する必要が
あることに注意してください。COPYEXECUTE

デフォルトでは、一時テーブルはセッションの最後に自動的に削除されます。
関連する回答:
PostreSQL で新しい行のみを一括挿入する方法

于 2013-08-22T07:49:32.817 に答える
0

私があなたを正しく理解していれば、いくつかのフィールドを持つ CSV ファイルがあり、PostgreSQL テーブルを検索するために使用される KEY が含まれています。

このタスクに使用できるプログラミング言語はわかりませんが、一般に、速度の問題を解決する必要があります。

最初の方法、プログラミング:

  1. CSV ファイルが 1 行あたり 500 バイトある場合でも、CSV ファイルをメモリにロードする必要があります。100000 * 500 = 50 メガバイトの RAM しか必要としません。
  2. CSV の KEY フィールドの検索インデックスを作成する必要があります。たとえば、PHP では、キーを KEY フィールド値に設定して配列を作成できます。C++ では、STD lib によって広く提示されているある種の HASH テーブルを作成できます。他のプログラミング言語では、そのバリアントが提供されます。
  3. PostgreSQL のテーブルは、キー フィールドに一致するフィールドによってインデックスを作成する必要があります。
  4. メモリにロードされた csv 配列を使用して、 "SELECT * FROM table WHERE key IN(1,2,3,4,5,6,7,8,9)" のようなクエリを作成します。ここで、"1,2,3,4 ..." - キーのフォーム CSV の一部 (たとえば、100) です。

2 番目の方法、自然な sql:

  1. テーブルを作成して CSV をロードする
  2. 検索に使用されるフィールドにインデックスを作成します
  3. 5Millions のテーブルにインデックスを作成する
  4. リンクされたテーブル データを取得するためのユーザー JOIN

選択する方法は、実際のタスクによって異なります。たとえば、私の経験では、価格表をデータベースにロードするためのインターフェースを作成する必要があり、実際にロードする前に、インポートされた XLS ファイルを「現在の」価格と「新しい」価格に関する情報とともに表示する必要がありました。ページネーションが必要なXLSファイルのサイズが大きいため、KEY IN(1,2,3,4,5,6)のバリアントが最適です。

于 2013-08-22T07:58:14.070 に答える