次の外部クエリは、320万行で実行されるのに約5秒かかります。
SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode")
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x
WHERE x."IncidentDateTime" >= '05/01/2016'
GROUP BY x."IncidentTypeCode"
ORDER BY 1;
通常のテーブルで同じクエリを実行すると、0.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
)
)
これは700k行を返します。これを回避する方法はありますか?
昨日 このドキュメントページ を読むのに多くの時間を費やし、use_remote_estimate
をtrueに設定して私の答えを見つけたと思いましたが、効果がありませんでした。
必要に応じて、外部サーバーにアクセスしてオブジェクトを作成します。 WHERE
句のタイムスタンプ値は任意です。事前定義された値のリストからのものではありません。
use_remote_estimate
を使用する場合は、必ず実行してください[〜#〜] analyze [〜#〜]外部テーブル(推定値が返されたのとかなり近いと思いますが、おそらくそれを行ったでしょう) 。また、プッシュダウンの改善は<9.5バージョンでは利用できません。また、リモートサーバーにも同じテーブル構造があることを前提としています(インデックスを含む)。カーディナリティが低いためにビットマップが必要な場合、プッシュダウンメカニズムの制限により、ビットマップはインデックスを使用しません。返される行の量を減らして、BTREEインデックススキャンを強制することができます(タイムスタンプ範囲)。残念ながら、フィルターがテーブルの行の+ 10%を返す場合、リモートサーバーでSeqScanを回避するためのクリーンな方法はありません(プランナーがテーブル全体のスキャンがシークリードよりも安いと考える場合、このパーセンテージが変わる可能性があります)。 SSDを使用している場合は、Tweak 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";