Hi,
Let me preface this by stating that I am not a PostgreSQL expert, so if there's something obvious I'm not understanding I apologize.
I'm writing a plugin that leverages pg_timeseries in an open source enterprise network monitoring platform. I'm using a simple time series schema:
Partitioned table "public.pgtimeseries_time_series"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------+--------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
key | text | | not null | | extended | | |
time | timestamp with time zone | | not null | | plain | | |
value | double precision | | | | plain | | |
Partition key: RANGE ("time")
Indexes:
"pgtimeseries_time_series_key_idx" btree (key)
"pgtimeseries_time_series_time_idx" btree ("time" DESC)
There are currently several hundred unique keys, but this could grow to tens of thousands for busy instances, making a table per datasource untenable.
# select count(distinct key) from pgtimeseries_time_series;
count
-------
637
(1 row)
Samples are collected every five minutes, but the interval is configurable per data source so it could be more or less frequently.
When using date_bin_table for time bucketting, I'm getting query plan results showing a lot of temp IO, as ~a million rows are selected and the filtered during the function scan, resulting in several hundred MB of read and write IO per query. I assume this is caused by the date_bin_table function selecting everything between the start time and end time, then filtering out rows that don't match the key?
=# explain (analyze, buffers) SELECT time AS step, COALESCE(avg(value), 'NaN') as aggregation FROM date_bin_table(NULL::pgtimeseries_time_series, '361 Seconds', '[2024-09-13 08:37:24.305, 2024-09-20 08:37:24.305]') where (key='name=G1YngCollCnt_resourceId=snmp/1/jvm/java_lang_type_GarbageCollector_name_G1_Young_Generation' OR key is null) GROUP BY step ORDER BY step;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=12.92..13.12 rows=10 width=16) (actual time=1400.602..1401.472 rows=1676 loops=1)
Group Key: "time"
Buffers: shared hit=116131 read=5947 written=5, temp read=53560 written=53607
-> Sort (cost=12.92..12.94 rows=10 width=16) (actual time=1400.590..1400.746 rows=2016 loops=1)
Sort Key: "time"
Sort Method: quicksort Memory: 159kB
Buffers: shared hit=116131 read=5947 written=5, temp read=53560 written=53607
-> Function Scan on date_bin_table (cost=0.25..12.75 rows=10 width=16) (actual time=1243.910..1399.759 rows=2016 loops=1)
Filter: ((key = 'name=G1YngCollCnt_resourceId=snmp/1/jvm/java_lang_type_GarbageCollector_name_G1_Young_Generation'::text) OR (key IS NULL))
Rows Removed by Filter: 994966
Buffers: shared hit=116128 read=5947 written=5, temp read=53560 written=53607
Planning:
Buffers: shared hit=19 read=2
Planning Time: 0.279 ms
Execution Time: 1416.850 ms
(15 rows)
See also: https://explain.depesz.com/s/G4gq
Granted, this development instance is quite under-resourced and the clock time here is illustrative of that, but as the total number of keys grows the absolute number of rows between a given start and end will grow, creating even more IO as more rows are selected and discarded.
Is there something in my schema design or query that violates the expected best practice for pg_timeseries that I should change to mitigate this circumstance? Are there indexes that date_bin_table expects or could take advantage of that I am missing?
Hi,
Let me preface this by stating that I am not a PostgreSQL expert, so if there's something obvious I'm not understanding I apologize.
I'm writing a plugin that leverages pg_timeseries in an open source enterprise network monitoring platform. I'm using a simple time series schema:
There are currently several hundred unique keys, but this could grow to tens of thousands for busy instances, making a table per datasource untenable.
Samples are collected every five minutes, but the interval is configurable per data source so it could be more or less frequently.
When using
date_bin_tablefor time bucketting, I'm getting query plan results showing a lot of temp IO, as ~a million rows are selected and the filtered during the function scan, resulting in several hundred MB of read and write IO per query. I assume this is caused by thedate_bin_tablefunction selecting everything between the start time and end time, then filtering out rows that don't match the key?See also: https://explain.depesz.com/s/G4gq
Granted, this development instance is quite under-resourced and the clock time here is illustrative of that, but as the total number of keys grows the absolute number of rows between a given start and end will grow, creating even more IO as more rows are selected and discarded.
Is there something in my schema design or query that violates the expected best practice for
pg_timeseriesthat I should change to mitigate this circumstance? Are there indexes thatdate_bin_tableexpects or could take advantage of that I am missing?