From: | - - <loh(dot)law(at)hotmail(dot)com> |
---|---|
To: | <pgsql-general(at)postgresql(dot)org> |
Subject: | Re: Slow query with sub-select |
Date: | 2011-07-16 23:14:38 |
Message-ID: | BAY147-W52EBF0D7C26204DA1DF028F0480@phx.gbl |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
> - - <loh(dot)law(at)hotmail(dot)com> writes:
> > The weird thing is that before I updated my server the query was about 5 times faster.
> > I've googled and I think the problem lies with the under-estimation of the query planner about the number of rows in the nested table.I will be trying the 'set enable_seqscan = false' solution to see if that'll improve.
>
> You evidently already do have that turned off. I'd suggest reverting
> that change (ie, allow seqscan) and instead increase work_mem enough
> so that the hash join can work without spilling to disk. This query
> is a perfect example of where indexes do not help, and trying to force
> them to be used makes things slower not faster.
>
> regards, tom lane
I have switched on seqscan and increased work_mem to 1GB ... but no luck so far.
The version I'm using is PostgreSQL 8.4.8 on i686-pc-linux-gnu, compiled by GCC gcc-4.5.real (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2, 32-bitBefore that I used an earlier minor version (8.4.x - I don't remember what x is but it was the one packaged in the version before Ubuntu Natty).
These are the relevant schemas.
CREATE TABLE q ( mid VARCHAR(10) NOT NULL ...);
CREATE TABLE t ( mid VARCHAR(10) NOT NULL PRIMARY KEY ...);
I would like to count rows in q whose mid does not exist in t.
This is the query I used.
SELECT COUNT(*) FROM q WHERE NOT EXISTS (SELECT 1 FROM t WHERE t.mid = q.mid);
Based on my understanding, I believe the query will loop through each row in q (which has about 500m rows) and for each row it will check a one-to-one mapping against t (which has about 3m rows) by using an index scan on t (mid).
However, the EXPLAIN outputs for seqscan = on and seqscan = off, respectively, seem to indicate that it is not a one-to-one mapping of t.mid and q.mid.
I then switched the comparison operator in the where clause as follows:
SELECT COUNT(*) FROM q WHERE NOT EXISTS (SELECT 1 FROM t WHERE q.mid = t.mid);
As there is no index on q (mid) this type of query should take a considerably longer time. However, the EXPLAIN outputs seem to be the same. Here they are:
With seqscan = on QUERY PLAN ------------------------------------------------------------------------------------- Aggregate (cost=18566199.92..18566199.93 rows=1 width=0) -> Hash Anti Join (cost=747023.15..18566199.91 rows=1 width=0) Hash Cond: ((q.mid)::text = (t.mid)::text) -> Seq Scan on q (cost=0.00..11451989.24 rows=565972224 width=10) -> Hash (cost=701775.29..701775.29 rows=3619829 width=10) -> Seq Scan on t (cost=0.00..701775.29 rows=3619829 width=10)(6 rows)
With seqscan = off QUERY PLAN ------------------------------------------------------------------------------------------------------- Aggregate (cost=10024599995.73..10024599995.74 rows=1 width=0) -> Hash Anti Join (cost=10006780818.96..10024599995.72 rows=1 width=0) Hash Cond: ((q.mid)::text = (t.mid)::text) -> Seq Scan on q (cost=10000000000.00..10011451989.24 rows=565972224 width=10) -> Hash (cost=6735571.10..6735571.10 rows=3619829 width=10) -> Index Scan using t_pkey on t (cost=0.00..6735571.10 rows=3619829 width=10)(6 rows)
Any help is greatly appreciated as this problem has been depressing me for two weeks.
From | Date | Subject | |
---|---|---|---|
Next Message | Rick Genter | 2011-07-16 23:40:10 | Re: Slow query with sub-select |
Previous Message | Michael Nolan | 2011-07-16 17:40:41 | Re: Slow query with sub-select |