1

2 つの異なる postgres 9.3 インスタンス (1 つは本番用、もう 1 つは開発/テスト用) を実行しています。本番環境のテーブルのサブセットを開発環境にコピーしたいと考えています。

次に、コピーしたいテーブルが次のように定義されているとしましょう

CREATE TABLE users (user_id varchar PRIMARY KEY, other_stuff varchar);

コピーしたいサブセットは、キャッシュされたテーブル (本番環境) に user_id を持つすべてのユーザーです。これは、users テーブルよりもはるかに小さいテーブルです。

CREATE TABLE user_id_subset (user_id varchar PRIMARY KEY);

これらの2つのテーブル(それぞれforeign_usersとforeign_user_id_subsetという名前)にアクセスするために、開発データベースにいくつかの外部テーブルを設定しました。次のようなクエリを実行したいと思います。

INSERT INTO development_users (user_id, other_stuff) 
    SELECT user_id, other_stuff FROM foreign_users f
    WHERE EXISTS (
        SELECT 1 FROM foreign_user_id_subset ss 
        WHERE ss.user_id=f.user_id)

このクエリは機能しますが、パフォーマンスが心配です。Explain の結果は次のようになります。

'Insert on development_users (cost=262.01..284.09 rows=138 width=272)'
'  ->  Hash Join  (cost=262.01..284.09 rows=138 width=272)'
'        Hash Cond: ((f.user_id)::text = (cache.user_id)::text)'
'        ->  Foreign Scan on foreign_users f  (cost=100.00..118.28 rows=276 width=272)'
'        ->  Hash  (cost=159.52..159.52 rows=200 width=32)'
'              ->  HashAggregate  (cost=157.52..159.52 rows=200 width=32)'
'                    ->  Foreign Scan on foreign_user_id_subset  (cost=100.00..153.86 rows=1462 width=32)'

私が考えているのは、開発データベースが本番データベースにリクエストを送信し、それがforeign_user_id_subset(本番環境ではuser_id_subset)の一時ハッシュを作成し、本番環境でハッシュチェックを行うことです。このように、(データベース間で) ネットワークを介して送信されるのは、最初の要求と、選択クエリの結果だけです。これは本当ですか?

別のアイデアは、本番データベースでこのリクエストの結果の「一時」(真の TEMP テーブルにすることはできません。外部テーブルが必要です)を作成し、次に外部テーブルを構築して、 SELECT * 外部テーブルの開発から。

(私の本番データベースは、私の開発データベースよりもはるかに高価でパフォーマンスの高い RDS インスタンスであることに注意してください)

4

1 に答える 1

0

私自身の質問に答えるには:

上記の代替案を実装しました。EXISTS クエリの結果のみを含むテーブルを本番環境で生成し、そのテーブルを参照するために開発環境で外部テーブルを作成しました。次に、サブセット テーブルを作成するために、「INSERT INTO ...SELECT * FROM ...」を実行しました。

これを使用すると、投稿された元の方法よりもタイミングが劇的に速くなりました。

本番環境でテーブルを作成する時間: Total runtime: 204.838 ms

開発データベースに挿入する時間:Total runtime: 1564.444 ms

そして、元の方法を実行するには:許容できないほど遅く、上記と同じ結果を達成するのに10分以上かかります(説明分析が完了するのを待ちませんでした)

プランナーが提供するものを超えた低レベルの命令を決定するより良い方法はわかりませんが、元の方法はシーケンシャル スキャン (外部テーブルのチャンクを繰り返しスキャンすることによって行われる) を実行し、ハッシュを実行すると信じています。開発データベースでの比較。

于 2015-07-28T21:15:31.163 に答える