外部データ ラッパー (postgres_fdw) を介して INNER JOIN を使用してクエリを実行しています。EXPLAIN ANALYZE を表示すると、Foreign Scan サブノードの 1 つが、実際には 7 行をスキャンするときに 1 行しかスキャンしないと過小評価されていることが示され、クエリが発生します。これにより、他の外部スキャン サブノードが 7 回ループし、これがクエリの主なボトルネックになるためです。クエリとそれぞれの EXPLAIN ANALYZE は次のとおりです。
SELECT ROUND(AVG(m.forecast - w.wind),6) from pjm.wind_forecast_recent w
INNER JOIN pjm.load_forecast_recent m ON w.pricedate = m.pricedate AND w.hour = m.hour
WHERE w.hour = 5 AND m.area = 'RTO_COMBINED' AND (w.pricedate BETWEEN (SELECT current_date-6) AND (SELECT current_date));
Aggregate (cost=842341.01..842341.02 rows=1 width=32) (actual time=77120.088..77120.089 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.007..0.008 rows=1 loops=1)
InitPlan 2 (returns $1)
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.001..0.001 rows=1 loops=1)
-> Nested Loop (cost=840333.25..842340.97 rows=1 width=18) (actual time=14719.661..77119.994 rows=7 loops=1)
-> Foreign Scan on wind_forecast_recent w (cost=242218.45..242218.49 rows=1 width=18) (actual time=3184.714..3184.720 rows=7 loops=1)
-> Foreign Scan on load_forecast_recent m (cost=598114.80..600122.47 rows=1 width=16) (actual time=10531.723..10531.724 rows=1 loops=7)
Planning Time: 744.979 ms
Execution Time: 77227.512 ms
default_statistics_target の値を 1000 に上げた後、両方のテーブルで ANALYZE を実行しようとしましたが、プランナーは変更されませんでした。
BETWEEN を使用してクエリの WHERE 部分を一連の OR ステートメントに変更した場合にも注意する必要があります。 、クエリはネストされたループを使用せず、7 倍の速度で実行されます。BETWEEN を使用したり、一連の OR ステートメントを使用しても同じ結果が得られる理由はよくわかりませんが、Foreign Scan の行数を過小評価しているプランナーに関係していると思います。
Ubuntu 18.04 サーバーで PostgreSQL 12.1 を実行しています。
ご不明な点がございましたら、お気軽にお問い合わせください。ありがとう!