postgres_fdwのパフォーマンスが遅い


12

外部に対する次のクエリは、320万行で実行するのに約5秒かかります。

SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode") 
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x 
WHERE x."IncidentDateTime" >= '05/01/2016' 
GROUP BY x."IncidentTypeCode" 
ORDER BY 1;

通常のテーブルで同じクエリを実行すると、.6秒で戻ります。実行計画はまったく異なります。

通常のテーブル

Sort  (cost=226861.20..226861.21 rows=4 width=4) (actual time=646.447..646.448 rows=7 loops=1) 
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB 
  -> HashAggregate (cost=226861.12..226861.16 rows=4 width=4) (actual  time=646.433..646.434 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Bitmap Heap Scan on "IntterraNearRealTimeUnitReflexes300s" x  (cost=10597.63..223318.41 rows=708542 width=4) (actual time=74.593..342.110 rows=709376 loops=1) 
        Recheck Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 
        Rows Removed by Index Recheck: 12259 
        Heap Blocks: exact=27052 lossy=26888
        -> Bitmap Index Scan on idx_incident_date_time_300  (cost=0.00..10420.49 rows=708542 width=0) (actual time=69.722..69.722 rows=709376 loops=1) 
           Index Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 

Planning time: 0.165 ms 
Execution time: 646.512 ms

外部テーブル

Sort  (cost=241132.04..241132.05 rows=4 width=4) (actual time=4782.110..4782.112 rows=7 loops=1)   
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB
  -> HashAggregate  (cost=241131.96..241132.00 rows=4 width=4) (actual time=4782.097..4782.100 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Foreign Scan on "IntterraNearRealTimeUnitReflexes300sForeign" x  (cost=10697.63..237589.25 rows=708542 width=4) (actual time=1.916..4476.946 rows=709376 loops=1) 

Planning time: 1.413 ms 
Execution time: 4782.660 ms

私はGROUP BY条項に高い代価を払っていると思いますEXPLAIN VERBOSE

SELECT
    "IncidentTypeCode"
FROM
    PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
WHERE
    (
        (
            "IncidentDateTime" >= '2016-05-01 00:00:00' :: TIMESTAMP WITHOUT TIME ZONE
        )
    )

これにより、70万行が返されます。これを回避する方法はありますか?

昨日、このドキュメントのページを読むのに多くの時間を費やし、use_remote_estimatetrueに設定して答えを見つけたと思ったが、効果はなかった。

必要に応じて、外部サーバーにアクセスしてオブジェクトを作成できます。WHERE句のタイムスタンプ値は何でもかまいません。定義済みの値のリストから取得されたものではありません。


3
9.6にはプッシュダウンの改良点がいくつかあります。wiki.postgresql.org
ジャックはtry tryanswers.xyz

通常のテーブルと外部テーブルと言う場合、同じテーブル(ローカルとリモート)で実行されているか、実際には異なるテーブル(あたかもそれらがそうであるかのように読み取ります)あなたは完全に異なる情報ソースを読んでいるように見えるとしてIntterraNearRealTimeUnitReflexes300sForeignIntterraNearRealTimeUnitReflexes300sidx_incident_date_time_300 私は300Sのものを推定同じですが、あればそれは価値があるかもしれないチェックidx_incident_date_time_300インデックスが外部サーバー上に存在している
マリーBOV

2
私が理解していることから、集計(COUNT)はリモートサーバーにプッシュされません。これは長い要求時間を説明します。-この機能は、PG 10に表示されるようだdepesz.com/2016/10/25/...
ジェロームWAGNER

@JeromeWAGNER -恐ろしい
J-DAWG

回答:


7

使用する場合はuse_remote_estimate、必ず外部テーブルのANALYZEを実行してください(返された値にかなり近い推定値が表示される場合は、おそらくそれを実行したでしょう)。また、バージョン9.5未満ではプッシュダウンの改善は利用できません。また、リモートサーバーでも同じテーブル構造(インデックスを含む)を持っていると仮定します。カーディナリティが低いためにビットマップが必要な場合、プッシュダウンメカニズムの制限のため、インデックスは使用されません。返される行の量を減らして、BTREEインデックススキャン(タイムスタンプ範囲)。残念ながら、フィルターがテーブルの行の+ 10%を返す場合、リモートサーバーでSeqScanを回避する明確な方法はありません(プランナーがテーブル全体のスキャンがシークリードよりも安価であると考える場合、この割合は異なる場合があります)。SSDを使用している場合は、おそらく微調整するのに役立つでしょうrandom_page_cost

CTEを使用して、GROUP BY動作を分離できます。

WITH atable AS (
    SELECT "IncidentTypeCode"
    FROM PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
    WHERE 
       ("IncidentDateTime" 
              BETWEEN '2016-05-01 00:00:00'::TIMESTAMP WITHOUT TIME ZONE 
                  AND '2016-05-02 00:00:00'::TIMESTAMP WITHOUT TIME ZONE)
)
SELECT atable."IncidentTypeCode", COUNT(atable.IncidentTypeCode) 
FROM atable
GROUP BY atable."IncidentTypeCode" 
ORDER BY atable."IncidentTypeCode";

1
CTEを使用したパフォーマンスは同じでした。ただし、random_page_cost設定を試行します。ありがとう!
J-DawG
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.