外部データラッパー
通常、結合またはサブクエリまたはCTEからの派生テーブルは、外部サーバーでは使用できないため、ローカルで実行する必要があります。つまり、単純なWHERE
の後に残っているすべての行 例の句は、観察したようにローカルで取得して処理する必要があります。
他のすべてが失敗した場合は、サブクエリSELECT id FROM lookup_table WHERE x = 5
を実行できます。 結果をクエリ文字列に連結します。
さらに便利なことに、動的SQLとEXECUTE
を使用してこれを自動化できます。 PL/pgSQL関数で。いいね:
CREATE OR REPLACE FUNCTION my_func(_c1 int, _l_id int)
RETURNS TABLE(id int, c1 int, c2 int, c3 int) AS
$func$
BEGIN
RETURN QUERY EXECUTE
'SELECT id,c1,c2,c3 FROM big_table
WHERE c1 = $1
AND id = ANY ($2)'
USING _c1
, ARRAY(SELECT l.id FROM lookup_table l WHERE l.x = _l_id);
END
$func$ LANGUAGE plpgsql;
関連:
- PostgreSQL関数パラメータとしてのテーブル名
または、SOでこの検索を試してください。
または、メタコマンド\gexec
を使用することもできます psqlで。参照:
- SQLDDLステートメントの既存のテーブルから列名をフィルタリングする
<ストライク>または これはうまくいくかもしれません: (フィードバックによると、機能しない 。)
<ストライク>ストライク>
SELECT id,c1,c2,c3
FROM big_table
WHERE c1 = 2
AND id = ANY (ARRAY(SELECT id FROM lookup_table WHERE x = 5));
ローカルでテストすると、次のようなクエリプランが表示されます:
Index Scan using big_table_idx on big_table (cost= ...) Index Cond: (id = ANY ($0)) Filter: (c1 = 2) InitPlan 1 (returns $0) -> Seq Scan on lookup_table (cost= ...) Filter: (x = 5)
大胆な強調鉱山。
パラメータ$0
計画の中で希望を刺激します。生成された配列は、Postgresがリモートで使用するために渡すことができるものである可能性があります。私はあなたの他の試みのいずれか、または私が自分で試したいくつかの試みと同様の計画を見ていません。 fdwでテストできますか?
postgres_fdw
に関する関連質問 :
- postgres_fdw:参加のためにデータを外部サーバーにプッシュすることは可能ですか?
SQLの一般的な手法
それは別の話です。 CTEを使用するだけです。しかし、それがFDWに役立つとは思いません。
WITH cte AS (SELECT id FROM lookup_table WHERE x = 5)
SELECT id,c1,c2,c3
FROM big_table b
JOIN cte USING (id)
WHERE b.c1 = 2;
PostgreSQL 12 いくつかの前提条件が与えられた場合に、CTEをサブクエリのようにインライン化できるように、動作を変更(改善)しました。しかし、マニュアルを引用すると:
MATERIALIZED
を指定することで、その決定を上書きできます。 WITHクエリの個別の計算を強制する
だから:
WITH cte AS MATERIALIZED (SELECT id FROM lookup_table WHERE x = 5)
...
通常、DBサーバーが適切に構成されていて、列の統計が最新である場合、これは必要ありません。しかし、データ分散が不均一なコーナーケースがあります...