PostgreSQL as a Time Series Database

The database is range partitioned into 24 partitions based on the ts field, the main table and the partitions are indexed on the timestamp (ts) and status fields.

Hardware spec

AMD Ryzen 7 5800x

128gb Corsair 3600 MT/s RAM

SABRENT M.2 NVMe SSD 1TB Gen 4, Internal Solid State

Debian Linux 12

PostgreSQL 15

With 380m rows in the database, this query is targeted at a specific partitions based on the timestamp field.

ts=# select * from ts where ts between ‘2023-02-09 00:00:00’ and ‘2023-02-09 06:00:00′ and status=’2xx’ order by ts limit 20;

(20 rows)

Time: 0.307 ms

ts=# select count(*) from ts where ts between ‘2023-02-09 00:00:00’ and ‘2023-02-09 06:00:00′ and status=’2xx’;

count

833067
(1 row)

Time: 91.614 ms

ts=# select status, count(*) from ts where ts between ‘2023-02-09 00:00:00’ and ‘2023-02-09 06:00:00’ group by status;
status | count
——–+——–
2xx | 833067
4xx | 356965
5xx | 119060
(3 rows)

Time: 121.393 ms

ts=# select * from ts where ts between ‘2023-01-09 00:00:00’ and ‘2023-01-09 06:00:00′ and status=’2xx’ order by ts limit 20;
id | ts | elapsed | type | key | status | esd

…. results omitted
(20 rows)

Time: 1.365 ms


ts=# explain select * from ts where ts between ‘2023-01-09 00:00:00’ and ‘2023-01-09 06:00:00′ and status=’2xx’ order by ts limit 20;

QUERY PLAN

Limit (cost=0.57..6.53 rows=20 width=165)
-> Index Scan using ts_part_0_ts_idx on ts_part_0 ts (cost=0.57..249850.66 rows=839044 width=165)
Index Cond: ((ts >= ‘2023-01-09 00:00:00’::timestamp without time zone) AND (ts <= ‘2023-01-09 06:00:00’::timestamp without time zone))
Filter: ((status)::text = ‘2xx’::text)
(4 rows)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.