Postgres 8.4 で約 5 秒で実行されるクエリがあります。他のテーブルに結合されたビューからデータを選択しますが、lag()ウィンドウ関数も使用します。
SELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...)
FROM view1 v
JOIN othertables USING (...)
WHERE ...
便宜上、単純な新しいビューを作成しました
SELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...)
FROM view1 v
そして、それから SELECT を行い、以前と同様に他のすべての JOIN とフィルターを使用します。驚いたことに、このクエリは 12 分以内に完了しません (その時点で停止しました)。明らかに、Postgres は別の実行計画を選択しました。そうしないようにするにはどうすればよいですか。元のクエリと同じプランを使用しますか? ビューが実行計画を変更するべきではないと私は思っていたでしょうが、どうやらそうです。
編集:さらに、最初のビューの内容を2番目のビューにコピーしても、まだ返されないことがわかりました。
編集 2: OK、計画を投稿するのに十分なほどクエリを単純化しました。
ビューの使用 (これは妥当な時間内に返されません):
Subquery Scan sp (cost=5415201.23..5892463.97 rows=88382 width=370)
Filter: (((sp.ticker)::text ~~ 'Some Ticker'::text) AND (sp.price_date >= '2010-06-01'::date))
-> WindowAgg (cost=5415201.23..5680347.20 rows=53029193 width=129)
-> Sort (cost=5415201.23..5441715.83 rows=53029193 width=129)
Sort Key: sp.stock_id, sp.price_date
-> Hash Join (cost=847.87..1465139.61 rows=53029193 width=129)
Hash Cond: (sp.stock_id = s.stock_id)
-> Seq Scan on stock_prices sp (cost=0.00..1079829.20 rows=53029401 width=115)
-> Hash (cost=744.56..744.56 rows=29519 width=18)
-> Seq Scan on stocks s (cost=0.00..744.56 rows=29519 width=18)
ビューからウィンドウ関数を取り出し、クエリ自体に入れます (これはすぐに返されます)。
WindowAgg (cost=34.91..34.95 rows=7 width=129)
-> Sort (cost=34.91..34.92 rows=7 width=129)
Sort Key: sp.stock_id, sp.price_date
-> Nested Loop (cost=0.00..34.89 rows=7 width=129)
-> Index Scan using stocks_ticker_unique on stocks s (cost=0.00..4.06 rows=1 width=18)
Index Cond: ((ticker)::text = 'Some Ticker'::text)
Filter: ((ticker)::text ~~ 'Some Ticker'::text)
-> Index Scan using stock_prices_id_date_idx on stock_prices sp (cost=0.00..30.79 rows=14 width=115)
Index Cond: ((sp.stock_id = s.stock_id) AND (sp.price_date >= '2010-06-01'::date))
したがって、遅いケースでは、最初にすべてのデータにウィンドウ関数を適用してからフィルタリングしようとしているようです。これがおそらく問題です。なぜそうしているのかはわかりませんが。