[英]PostgreSQL generate_series strange behaviour
以下兩個查詢產生完全相同的輸出:
select
ref_date::date
from generate_series('2020-10-01', '2020-10-01'::date, interval '1 day') ref_date
-- ref_date
-- 2020-10-01
select now()::date ref_date
-- ref_date
-- 2020-10-01
但是,在對它們中的每一個運行explain
時,我們會得到不同的結果:
# query 1
Function Scan on generate_series ref_date (cost=0.01..12.51 rows=1000 width=4)
# query 2
Result (cost=0.00..0.01 rows=1 width=4)
當在一系列連接中包含一個或另一個時,情況會變得更糟,連接條件基於ref_date
:
select
stuff
from (select ref_date::date from generate_series('2020-10-01', '2020-10-01'::date, interval '1 day') ref_date) ref_date
left join (other_stuff) x on true
left join (more_stuff) y on y.id = x.id and y.timestamp < ref_date
-- executes in 10 minutes
-- EXPLAIN is long and complex
-- query uses index on more_stuff.(id) only
despite an index on (id, timestamp) being available
select
stuff
from (select now()::date ref_date) ref_date
left join (other_stuff) x on true
left join (more_stuff) y on y.id = x.id and y.timestamp < ref_date
-- executes in ten milliseconds
-- EXPLAIN is short and simple
-- query adequately uses index on more_stuff.(id, timestamp)
我不能在現實中使用now()::date
的原因是我需要generate_series()
來生成多個日期(例如,跨越 5 年)。
問題:
有沒有一種方法可以使用使用日期序列的替代方法,並且與在上述示例中使用now()::date
時一樣有效?
筆記:
generate_series()
方法的性能也比now()::date
差很多相關子查詢可以滿足您的要求。
select stuff
FROM generate_series('2020-09-01'::date, '2020-10-01'::date, interval '1 day') as ref_date
LEFT JOIN LATERAL
(select (other_stuff)) AS x on true
left join (more_stuff) y on y.timestamp < ref_date
這應該生成一個嵌套循環連接,內部部分的計划與您的快速查詢相匹配。 LATERAL 關鍵字強制數據庫為左側的每一行重新評估右側。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.