I'm not very experienced with database query optimization. I've been reading through similar questions here and Postgres tuning articles online, but unfortunately I haven't had any luck. Here's what I have (DB version, table information, number of rows, EXPLAIN ANALYZE
of the two queries I would like to optimize):
foodb=# SELECT version();
version
---------------------------------------------------------------------------------------------------------------
PostgreSQL 9.3.4 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-52), 64-bit
(1 row)
foodb=# \d+ datapoints
Table "public.datapoints"
Column | Type | Modifiers | Storage | Stats target | Description
--------+-----------------------------+-----------+----------+--------------+-------------
tag | character varying(200) | not null | extended | |
time | timestamp without time zone | not null | plain | |
value | double precision | | plain | |
Indexes:
"ix_datapoints_tag" btree (tag)
"ix_datapoints_tag_time_value" btree (tag, "time", value)
Has OIDs: no
foodb=# SELECT COUNT(*) FROM datapoints;
count
-----------
162727709
(1 row)
foodb=# EXPLAIN ANALYZE SELECT DISTINCT tag FROM datapoints;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=5035440.60..5035691.99 rows=25139 width=106) (actual time=74304.278..74357.708 rows=218367 loops=1)
-> Seq Scan on datapoints (cost=0.00..4641784.68 rows=157462368 width=106) (actual time=0.019..24484.872 rows=162727709 loops=1)
Total runtime: 74371.153 ms
(3 rows)
foodb=# EXPLAIN ANALYZE SELECT tag, min(time) as minTime, max(time) as maxTime FROM datapoints GROUP BY tag;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=5822752.44..5823003.83 rows=25139 width=114) (actual time=86848.009..86908.264 rows=218367 loops=1)
-> Seq Scan on datapoints (cost=0.00..4641784.68 rows=157462368 width=114) (actual time=0.010..19226.031 rows=162727709 loops=1)
Total runtime: 86922.564 ms
(3 rows)
I tried to make the following configuration changes in postgresql.conf
, but couldn't see much performance improvement:
max_connections = 128 // was 300
work_mem = 64m // was 8m
shared_buffers = 4096m // was 128m
effective_cache_size = 4096m // was 128m
What do you suggest so that I can improve the performance of these two queries?
SELECT DISTINCT tag FROM datapoints;
SELECT tag, min(time) as minTime, max(time) as maxTime FROM datapoints GROUP BY tag;
Update 1:
Turning off sequential scan doesn't seem to help much.
foodb=# set enable_seqscan = off;
SET
foodb=# EXPLAIN ANALYZE SELECT DISTINCT tag FROM datapoints;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Unique (cost=0.82..591769146.07 rows=25139 width=106) (actual time=0.037..81086.671 rows=218367 loops=1)
-> Index Only Scan using ix_datapoints_tag on datapoints (cost=0.82..591375490.15 rows=157462368 width=106) (actual time=0.033..54393.956 rows=162727709 loops=1)
Heap Fetches: 162727709
Total runtime: 81104.455 ms
(4 rows)
Update 2:
Tried creating an index on time
column, and ran the second query, still no luck.
foodb=# CREATE INDEX ix_datapoints_time ON datapoints(time);
CREATE INDEX
foodb=# EXPLAIN ANALYZE SELECT tag, min(time) as minTime, max(time) as maxTime FROM datapoints GROUP BY tag;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=5914895.96..5915147.35 rows=25139 width=114) (actual time=91870.389..91931.164 rows=218367 loops=1)
-> Seq Scan on datapoints (cost=0.00..4694438.12 rows=162727712 width=114) (actual time=0.013..24101.108 rows=162727709 loops=1)
Total runtime: 91944.348 ms
(3 rows)
DISTINCT tag
is using Sequence scan might be because you have bigger percentage of distinct values comparing with those which are not so it wouldn't benefit from an index scan in this case.time
index after this, do you still suggest creating it?ANALYZE datapoints
after creating index? Please try toCREATE INDEX idx_test_01 ON datapoints(tag, time)
thenANALYZE datapoints
and thenEXPLAIN ...
if you could.