I also observe slow planning and marking function as immutable doesn’t help a lot.
Let’s look at example with weather metrics:
create materialized view wmd with (timescaledb.continuous) as select time_bucket('1 day', time) as bucket, city_name, avg(temp_c) as avg_temp, avg(feels_like_c) as feels_like_temp,
max(temp_c) as max_temp,
min(temp_c) as min_temp,
avg(pressure_hpa) as pressure,
avg(humidity_percent) as humidity_percent,
avg(rain_3h_mm) as rain_3h,
avg(snow_3h_mm) as snow_3h,
avg(wind_speed_ms) as wind_speed,
avg(clouds_percent) as clouds from weather_metrics group by bucket, city_name with data;
create function inow3()
returns timestamp with time zone immutable
language sql
as $$ select '2022-05-05 14:55:15.772397+00'::timestamp with time zone $$ ;
Compare immutable function returning constant value and now()
.
explain (analyze on) select * from wmd where bucket between (inow3() - interval '4 year 1 day') and (inow3() - interval '4 year') and city_name = 'Lisbon' ;
Append (cost=538.24..7093.74 rows=421 width=121) (actual time=0.092..0.102 rows=1 loops=1)
-> GroupAggregate (cost=538.24..552.46 rows=200 width=121) (actual time=0.091..0.092 rows=1 loops=1)
Group Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.city_name
-> Sort (cost=538.24..538.80 rows=222 width=478) (actual time=0.029..0.030 rows=1 loops=1)
Sort Key: _materialized_hypertable_4.bucket
Sort Method: quicksort Memory: 25kB
-> Custom Scan (ChunkAppend) on _materialized_hypertable_4 (cost=0.15..529.59 rows=222 width=478) (actual time=0.021..0.023 rows=1 loops=1)
Chunks excluded during startup: 221
-> Index Scan Backward using _hyper_4_2416_chunk__materialized_hypertable_4_city_name_bucket on _hyper_4_2416_chunk (cost=0.29..2.51 rows=1 width=479) (actual time=0.021..0.022 rows=1 loops=1)
Index Cond: ((city_name = 'Lisbon'::text) AND (bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(4)), '-infinity'::timestamp without time zone)) AND (bucket >= ('2022-05-05 14:55:15.772397+00'::timestamp with time zone - '4 years 1 day'::interval)) AND (bucket <= ('2022-05-05 14:55:15.772397+00'::timestamp with time zone - '4 years'::interval)))
-> HashAggregate (cost=6527.78..6534.97 rows=221 width=121) (actual time=0.008..0.008 rows=0 loops=1)
Group Key: time_bucket('1 day'::interval, wm."time"), wm.city_name
Batches: 1 Memory Usage: 40kB
-> Custom Scan (ChunkAppend) on wm (cost=0.15..6461.51 rows=2209 width=77) (actual time=0.006..0.006 rows=0 loops=1)
Chunks excluded during startup: 2208
-> Index Scan Backward using _hyper_2_2209_chunk_weather_metrics_time_idx on _hyper_2_2209_chunk (cost=0.28..2.51 rows=1 width=77) (actual time=0.006..0.006 rows=0 loops=1)
Index Cond: ("time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(4)), '-infinity'::timestamp without time zone))
Filter: ((city_name = 'Lisbon'::text) AND (time_bucket('1 day'::interval, "time") >= ('2022-05-05 14:55:15.772397+00'::timestamp with time zone - '4 years 1 day'::interval)) AND (time_bucket('1 day'::interval, "time") <= ('2022-05-05 14:55:15.772397+00'::timestamp with time zone - '4 years'::interval)))
Planning Time: 1056.333 ms
Execution Time: 22.889 ms
explain (analyze on) select * from wmd where bucket between (now() - interval '4 year 1 day') and (now() - interval '4 year') and city_name = 'Lisbon' ;
Append (cost=539.35..7149.01 rows=421 width=121) (actual time=0.091..0.103 rows=1 loops=1)
-> GroupAggregate (cost=539.35..553.57 rows=200 width=121) (actual time=0.090..0.091 rows=1 loops=1)
Group Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.city_name
-> Sort (cost=539.35..539.91 rows=222 width=478) (actual time=0.028..0.029 rows=1 loops=1)
Sort Key: _materialized_hypertable_4.bucket
Sort Method: quicksort Memory: 25kB
-> Custom Scan (ChunkAppend) on _materialized_hypertable_4 (cost=0.16..530.70 rows=222 width=478) (actual time=0.022..0.023 rows=1 loops=1)
Chunks excluded during startup: 221
-> Index Scan Backward using _hyper_4_2416_chunk__materialized_hypertable_4_city_name_bucket on _hyper_4_2416_chunk (cost=0.29..2.51 rows=1 width=479) (actual time=0.021..0.022 rows=1 loops=1)
Index Cond: ((city_name = 'Lisbon'::text) AND (bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(4)), '-infinity'::timestamp without time zone)) AND (bucket >= (now() - '4 years 1 day'::interval)) AND (bucket <= (now() - '4 years'::interval)))
-> HashAggregate (cost=6581.95..6589.13 rows=221 width=121) (actual time=0.007..0.011 rows=0 loops=1)
Group Key: time_bucket('1 day'::interval, wm."time"), wm.city_name
Batches: 1 Memory Usage: 40kB
-> Custom Scan (ChunkAppend) on wm (cost=0.15..6515.68 rows=2209 width=77) (actual time=0.006..0.010 rows=0 loops=1)
Chunks excluded during startup: 2208
-> Index Scan Backward using _hyper_2_2209_chunk_weather_metrics_time_idx on _hyper_2_2209_chunk (cost=0.28..2.51 rows=1 width=77) (actual time=0.005..0.009 rows=0 loops=1)
Index Cond: ("time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(4)), '-infinity'::timestamp without time zone))
Filter: ((city_name = 'Lisbon'::text) AND (time_bucket('1 day'::interval, "time") >= (now() - '4 years 1 day'::interval)) AND (time_bucket('1 day'::interval, "time") <= (now() - '4 years'::interval)))
Planning Time: 1035.543 ms
Execution Time: 24.603 ms
Planning step duration is the same.
Replacing function with literal value makes the difference.
explain (analyze on) select * from wmd where bucket between ('2022-05-05 14:55:15.772397+00'::timestamp - interval '4 year 1 day') and ('2022-05-05 14:55:15.772397+00'::timestamp - interval '4 year') and city_name = 'Lisbon' ;
Append (cost=0.28..12.82 rows=2 width=121) (actual time=0.063..0.067 rows=1 loops=1)
-> GroupAggregate (cost=0.28..2.57 rows=1 width=121) (actual time=0.063..0.063 rows=1 loops=1)
Group Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.city_name
-> Custom Scan (ChunkAppend) on _materialized_hypertable_4 (cost=0.28..2.50 rows=1 width=479) (actual time=0.012..0.014 rows=1 loops=1)
Order: _materialized_hypertable_4.bucket
Chunks excluded during startup: 0
-> Index Scan Backward using _hyper_4_2416_chunk__materialized_hypertable_4_city_name_bucket on _hyper_4_2416_chunk (cost=0.28..2.50 rows=1 width=479) (actual time=0.012..0.014 rows=1 loops=1)
Index Cond: ((city_name = 'Lisbon'::text) AND (bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(4)), '-infinity'::timestamp without time zone)) AND (bucket >= '2018-05-04 14:55:15.772397'::timestamp without time zone) AND (bucket <= '2018-05-05 14:55:15.772397'::timestamp without time zone))
-> GroupAggregate (cost=10.16..10.22 rows=1 width=121) (actual time=0.002..0.003 rows=0 loops=1)
Group Key: (time_bucket('1 day'::interval, wm."time")), wm.city_name
-> Sort (cost=10.16..10.16 rows=1 width=77) (actual time=0.002..0.002 rows=0 loops=1)
Sort Key: (time_bucket('1 day'::interval, wm."time"))
Sort Method: quicksort Memory: 25kB
-> Custom Scan (ChunkAppend) on wm (cost=1.48..10.15 rows=1 width=77) (actual time=0.000..0.000 rows=0 loops=1)
Chunks excluded during startup: 1
Planning Time: 48.087 ms
Execution Time: 0.151 ms
Environment is lastest docker image with pg14 on Core i7 16ram.
SELECT default_version, installed_version FROM pg_available_extensions
ts1-# where name = 'timescaledb';
default_version | installed_version
-----------------+-------------------
2.6.1 | 2.6.1
version
---------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 14.2 (Ubuntu 14.2-1.pgdg22.04+1+b1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.2.0-16ubuntu1) 11.2.0, 64-bit