sql >> データベース >  >> RDS >> PostgreSQL

外部サーバーに参加/プッシュダウンする前にサブクエリの評価を強制する方法

    外部データラッパー

    通常、結合またはサブクエリまたは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サーバーが適切に構成されていて、列の統計が最新である場合、これは必要ありません。しかし、データ分散が不均一なコーナーケースがあります...




    1. SQL ServerのCONVERT()とTRY_CONVERT:違いは何ですか?

    2. トップ7データベース

    3. 無効な識別子SQL

    4. 接続文字列でサービス名の代わりにSIDを使用すると、cx_Oracleが接続しません