我有一个在 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
然后从中选择,像以前一样使用所有其他 JOIN 和过滤器。令我惊讶的是,这个查询没有在 12 分钟内完成(我当时停止了它)。显然 Postgres 选择了不同的执行计划。我如何让它不这样做,即。使用与原始查询相同的计划?我原以为视图不应该改变执行计划,但显然它确实如此。
编辑:更重要的是,我发现即使我将第一个视图的内容复制到第二个视图中,它仍然不会返回。
编辑 2:好的,我已经充分简化了查询以发布计划。
使用视图(这不会在任何合理的时间内返回):
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))
因此,在缓慢的情况下,它似乎首先尝试将窗口函数应用于所有数据,然后对其进行过滤,这可能是问题所在。不过,我不知道它为什么会这样做。