Re: [PERFORM] Why do my hash joins turn to nested loops?

2008-08-22 Thread pgsql-performance
On Thu, 21 Aug 2008, Tom Lane wrote:
> I think you need to raise from_collapse_limit and/or
> join_collapse_limit.

Ahah, that was it.. a much simpler solution than I was fearing.

I had already re-written the queries to get around it, but ran into 
another snag with that method, so this was good timing.

Thanks!

--
Ian Smith
www.ian.org

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Why do my hash joins turn to nested loops?

2008-08-21 Thread Tom Lane
[EMAIL PROTECTED] writes:
> One query works fast, returning results in under a second.  If I insert 
> one more join into the table however, it switches to nested-loops and 
> takes minutes.

I think you need to raise from_collapse_limit and/or
join_collapse_limit.

regards, tom lane

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


[PERFORM] Why do my hash joins turn to nested loops?

2008-08-21 Thread pgsql-performance
I only have a few days of experience with postgres and it is working 
great, but when I start building up test queries I ran into a problem I 
don't understand.

One query works fast, returning results in under a second.  If I insert 
one more join into the table however, it switches to nested-loops and 
takes minutes.  It does this randomly.. using integer compares in the 
query lines is fast for instance, but using LIKE operators causes it to 
use loops again.

I have about 200,000 items per table, so nested loops cause lots of pain.
The database has objects with lots (100 to 1000) 'specs' for each object 
in another table, so I have to pull them out to do queries and sorting on 
them.

Here are the two queries.  They are the same except the first has 
two 'find' joins and the other has three.

I assume that I am hitting some limit somewhere that is causing postgres 
to change it's idea on how to run the query.  Can I force it to use hash 
joins?

Thanks!

So this is fast... 

EXPLAIN ANALYZE SELECT * FROM logical 
LEFT JOIN model ON logical.uid = model.logical_uid 
LEFT JOIN company ON model.company_uid = company.uid 
LEFT JOIN type ON logical.type::INT = type.uid 
JOIN specs spec_find1 ON spec_find1 .spec_uid='8' AND spec_find1 .text LIKE '%' 
AND spec_find1 .logical_uid=model.logical_uid 
JOIN specs spec_find2 ON spec_find2.spec_uid='8' AND spec_find2.text LIKE '%' 
AND spec_find2.logical_uid=model.logical_uid 
LEFT JOIN specs specs_sort ON specs_sort.spec_uid='4' AND 
specs_sort.logical_uid=logical.uid 
ORDER BY specs_sort.num;

   
QUERY PLAN  
  
-
 Sort  (cost=5398.43..5398.44 rows=6 width=247) (actual time=331.546..333.303 
rows=3555 loops=1)
   Sort Key: specs_sort.num
   Sort Method:  quicksort  Memory: 981kB
   ->  Hash Left Join  (cost=1087.68..5398.35 rows=6 width=247) (actual 
time=37.309..315.451 rows=3555 loops=1)
 Hash Cond: (model.company_uid = company.uid)
 ->  Hash Left Join  (cost=1086.28..5396.86 rows=6 width=217) (actual 
time=37.235..308.787 rows=3555 loops=1)
   Hash Cond: (logical.uid = specs_sort.logical_uid)
   ->  Hash Left Join  (cost=694.84..5004.96 rows=6 width=180) 
(actual time=22.433..284.832 rows=3555 loops=1)
 Hash Cond: ((logical.type)::integer = type.uid)
 ->  Nested Loop  (cost=693.55..5003.62 rows=6 width=168) 
(actual time=22.361..273.502 rows=3555 loops=1)
   ->  Hash Join  (cost=693.55..4953.84 rows=6 
width=110) (actual time=22.330..237.717 rows=3555 loops=1)
 Hash Cond: (model.logical_uid = 
spec_find1.logical_uid)
 ->  Seq Scan on model  (cost=0.00..3337.82 
rows=184182 width=36) (actual time=0.017..99.289 rows=184182 loops=1)
 ->  Hash  (cost=691.60..691.60 rows=156 
width=74) (actual time=21.795..21.795 rows=2196 loops=1)
   ->  Hash Join  (cost=339.84..691.60 
rows=156 width=74) (actual time=8.558..19.060 rows=2196 loops=1)
 Hash Cond: (spec_find1.logical_uid 
= spec_find2.logical_uid)
 ->  Seq Scan on specs spec_find1  
(cost=0.00..326.89 rows=1036 width=37) (actual time=0.023..6.765 rows=2196 
loops=1)
   Filter: (((text)::text ~~ 
'%'::text) AND (spec_uid = 8))
 ->  Hash  (cost=326.89..326.89 
rows=1036 width=37) (actual time=8.508..8.508 rows=2196 loops=1)
   ->  Seq Scan on specs 
spec_find2  (cost=0.00..326.89 rows=1036 width=37) (actual time=0.010..6.667 
rows=2196 loops=1)
 Filter: (((text)::text 
~~ '%'::text) AND (spec_uid = 8))
   ->  Index Scan using logical_pkey on logical  
(cost=0.00..8.28 rows=1 width=58) (actual time=0.006..0.007 rows=1 loops=3555)
 Index Cond: (logical.uid = model.logical_uid)
 ->  Hash  (cost=1.13..1.13 rows=13 width=12) (actual 
time=0.024..0.024 rows=13 loops=1)
   ->  Seq Scan on type  (cost=0.00..1.13 rows=13 
width=12) (actual time=0.004..0.011 rows=13 loops=1)
   ->  Hash  (cost=287.57..287.57 rows=8309 width=37) (actual 
time=14.773..14.773 rows=8172 loops=1)
 ->  Seq Scan on specs specs_sort  (cost=0.00..287.57 
rows=8309 width=37) (actual time=0.012..8.206 rows=8172 loops=1)
   Filter: (spec_uid = 4)
 ->  Hash  (cost=1.18..1.1