Ich habe eine Abfrage, die in etwa 5 Sekunden auf Postgres 8.4 ausgeführt wird. Er wählt Daten aus einer Ansicht aus, die mit anderen Tabellen verbunden ist, verwendet aber auch die Fensterfunktion lag(), d.Encapsulating Postgres Query in Sicht macht es extrem langsam
SELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...)
FROM view1 v
JOIN othertables USING (...)
WHERE ...
Der Einfachheit halber habe ich eine neue Ansicht, die einfach
aus, dassSELECT *, lag(column1) OVER (PARTITION BY key1 ORDER BY ...), lag(...)
FROM view1 v
und dann SELECT hat, mit all den anderen JOIN und Filter wie zuvor. Zu meiner Überraschung wird diese Abfrage nicht in 12 Minuten abgeschlossen (ich habe es an diesem Punkt gestoppt). Offensichtlich hat Postgres einen anderen Ausführungsplan gewählt. Wie bekomme ich es, das nicht zu tun, dh. Verwenden Sie den gleichen Plan wie in der ursprünglichen Abfrage? Ich hätte gedacht, dass eine Ansicht den Ausführungsplan nicht ändern sollte, aber anscheinend tut es das.
Edit: was mehr ist, fand ich, dass selbst wenn ich den Inhalt der ersten Ansicht in den zweiten kopieren immer noch nicht zurückgibt.
Edit 2: OK, ich habe die Abfrage ausreichend vereinfacht, um die Pläne zu veröffentlichen.
die Ansicht verwenden (diese Rückkehr nicht in jeder angemessenen Zeit):
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)
Unter der Fensterfunktion aus dem Blick und setzt in die Abfrage selbst (dies liefert ab sofort):
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))
So scheint es, dass in dem langsamen Fall es versucht, die Fensterfunktion auf alle Daten zuerst zu übernehmen und es dann filtern, was wahrscheinlich das Problem. Ich weiß nicht, warum es das tut.
+1, aber ich vermute stark, dass Sie die '...' Teile ausfüllen müssen, bevor jemand diagnostizieren kann, was vor sich geht. – Edmund
könnte ich, aber die Abfrage ist ziemlich komplex und ich müsste erklären, wie alle relevanten Tabellen auch aussehen. Meine Frage bezieht sich eher auf eine generische Lösung für diese eher spezifische Abfrage: Gibt es eine Möglichkeit, Postgres mitzuteilen, dass es eine Sicht "durchschaut" und denselben Abfrageplan verwendet, als ob ich die zugrunde liegende SQL direkt eingegeben hätte. – EMP
Abfrage Ausführungspläne? EXPLAIN SELECT ... –