Forcing seq_scan off for large table joined with tiny table yeilds improved performance

From: Mario Splivalo <mario(dot)splivalo(at)megafon(dot)hr>
To: pgsql-performance(at)postgresql(dot)org
Subject: Forcing seq_scan off for large table joined with tiny table yeilds improved performance
Date: 2009-03-30 14:07:51
Message-ID: 49D0D237.7020308@megafon.hr
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-performance

I have two tables, like this:

Big table:

CREATE TABLE photo_info_data
(
photo_id integer NOT NULL,
field_name character varying NOT NULL,
field_value character varying,
CONSTRAINT photo_info_data_pk PRIMARY KEY (photo_id, field_name)
)
WITH (OIDS=FALSE);

CREATE INDEX user_info_data_ix_field_value
ON user_info_data
USING btree
(field_value);

Small table:

CREATE TABLE t_query_data
(
i integer,
"key" character varying,
op character varying,
"value" character varying
)
WITH (OIDS=FALSE);

I have around 2400000 rows in photo_info_data, and just two rows in
t_query_data:
i | key | op | value
---+----------+----+--------
1 | f-stop | eq | 2.6
2 | shutter | gt | 1/100

This is the query I'm executing:

SELECT
*
FROM
photo_info_data u
JOIN t_query_data t on u.field_name = key

This query takes around 900ms to execute. It returns 6 rows.

When I do 'explain analyze' for some reason it takes around 7 seconds,
and this is what I get:

phototest=# explain analyze select * from photo_info_data u join
t_query_data t on u.field_name = key;
QUERY PLAN

------------------------------------------------------------------------------------------------------------------------------------
Hash Join (cost=1.04..58676.31 rows=218048 width=68) (actual
time=2381.895..7087.225 rows=6 loops=1)
Hash Cond: ((u.field_name)::text = (t.key)::text)
-> Seq Scan on photo_info_data u (cost=0.00..47500.30 rows=2398530
width=50) (actual time=0.042..3454.112 rows=2398446 loops=1)
-> Hash (cost=1.02..1.02 rows=2 width=18) (actual
time=0.016..0.016 rows=2 loops=1)
-> Seq Scan on t_query_data t (cost=0.00..1.02 rows=2
width=18) (actual time=0.003..0.007 rows=2 loops=1)
Total runtime: 7087.291 ms
(6 rows)

Time: 7088.663 ms

I can rerun this query many times, it's always around 7 seconds. I/O
wait during the query is nonexistant, it just takes 100% of CPU time (i
have a DualCore Opteron server).

If I force the planner not to use sequential_scan, here is what I get:

phototest=# explain analyze select * from photo_info_data u join
t_query_data t on u.field_name = key;
QUERY
PLAN
---------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=100039134.84..100130206.79 rows=218048 width=68)
(actual time=271.138..540.998 rows=6 loops=1)
-> Seq Scan on t_query_data t (cost=100000000.00..100000001.02
rows=2 width=18) (actual time=0.008..0.015 rows=2 loops=1)
-> Bitmap Heap Scan on photo_info_data u (cost=39134.84..63740.08
rows=109024 width=50) (actual time=270.464..270.469 rows=3 loops=2)
Recheck Cond: ((u.field_name)::text = (t.key)::text)
-> Bitmap Index Scan on photo_info_data_pk
(cost=0.00..39107.59 rows=109024 width=0) (actual time=270.435..270.435
rows=3 loops=2)
Index Cond: ((u.field_name)::text = (t.key)::text)
Total runtime: 541.065 ms
(7 rows)

Time: 542.147 ms

The database currently has only those two tables. I have vacuumed them
prior running above queries.

I tought this information also might be important:
phototest=# select key, count(*) from photo_info_data u join
t_query_data t on u.field_name = key group by key;
key | count
----------+-------
f-stop | 3
shutter | 3
(2 rows)

Am I doing something wrong here? The photo_info_data would hold around
10.000.000 records, should I be doing 'set seq_scan to false' each time
I will want to run this query? (Since I'm accessing postgres trough JDBC
I'll have same situation I had weeks ago, I described it here also).

Mike

Responses

Browse pgsql-performance by date

  From Date Subject
Next Message Tom Lane 2009-03-30 14:16:11 Re: Forcing seq_scan off for large table joined with tiny table yeilds improved performance
Previous Message Alexander Staubo 2009-03-30 11:24:55 Re: Bad plan for nested loop + limit