Re: Bad plan by Planner (Already resolved?)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Robins Tharakan <robins.tharakan@xxxxxxxxxx> writes:
> ORIGINAL QUERY (on PostgreSQL 8.4.9):
> http://explain.depesz.com/s/bTm

> EXPLAIN ANALYZE SELECT field_a FROM large_table_a JOIN large_table_b 
> USING (field_a) WHERE field_b IN (SELECT large_table_b.field_b FROM 
> large_table_b WHERE field_a = 2673056) ;

> ------------------------------------------------------------------------------------------------------------------------------------------------------------
>   Nested Loop  (cost=132.97..194243.54 rows=156031 width=4) (actual 
> time=6.612..43179.524 rows=2120 loops=1)
>     ->  Nested Loop  (cost=132.97..1107.63 rows=156031 width=4) (actual 
> time=6.576..29122.017 rows=6938 loops=1)
>           ->  HashAggregate  (cost=132.97..133.96 rows=99 width=4) 
> (actual time=6.543..12.726 rows=2173 loops=1)
>                 ->  Index Scan using "IX_large_table_b_SigId" on 
> large_table_b  (cost=0.00..132.56 rows=164 width=4) (actual 
> time=0.029..3.425 rows=2173 loops=1)
>                       Index Cond: (field_a = 2673056)
>           ->  Index Scan using "IX_large_table_b_field_b" on 
> large_table_b  (cost=0.00..9.81 rows=2 width=8) (actual 
> time=6.732..13.384 rows=3 loops=2173)
>                 Index Cond: (public.large_table_b.field_b = 
> public.large_table_b.field_b)
>     ->  Index Scan using "PK_large_table_a" on large_table_a 
> (cost=0.00..1.23 rows=1 width=4) (actual time=2.021..2.021 rows=0 
> loops=6938)
>           Index Cond: (large_table_a.field_a = public.large_table_b.field_a)
>   Total runtime: 43182.975 ms


> OPTIMIZED QUERY (on PostgreSQL 8.4.7):
> http://explain.depesz.com/s/emO

> EXPLAIN ANALYZE SELECT s1.field_a FROM large_table_a JOIN large_table_b 
> s1 USING (field_a) JOIN large_table_b s2 ON s1.field_b = s2.field_b 
> WHERE s2.field_a = 2673056;

> ------------------------------------------------------------------------------------------------------------------------------------------------------------
>   Nested Loop  (cost=0.00..2356.98 rows=494 width=4) (actual 
> time=0.086..96.056 rows=2120 loops=1)
>     ->  Nested Loop  (cost=0.00..1745.51 rows=494 width=4) (actual 
> time=0.051..48.900 rows=6938 loops=1)
>           ->  Index Scan using "IX_large_table_b_SigId" on large_table_b 
> s2  (cost=0.00..132.56 rows=164 width=4) (actual time=0.028..3.411 
> rows=2173 loops=1)
>                 Index Cond: (field_a = 2673056)
>           ->  Index Scan using "IX_large_table_b_field_b" on 
> large_table_b s1  (cost=0.00..9.81 rows=2 width=8) (actual 
> time=0.007..0.012 rows=3 loops=2173)
>                 Index Cond: (s1.field_b = s2.field_b)
>     ->  Index Scan using "PK_large_table_a" on large_table_a 
> (cost=0.00..1.23 rows=1 width=4) (actual time=0.004..0.004 rows=0 
> loops=6938)
>           Index Cond: (large_table_a.field_a = s1.field_a)
>   Total runtime: 98.165 ms


I suspect that you're just fooling yourself here, and the "optimized"
query is no such thing.  Those plans are identical except for the
insertion of the HashAggregate step, which in itself adds less than
10msec to the runtime, and we can see it's not eliminating any rows
either.  So why does the second one run so much faster?  I can think
of three theories:

1. The tables are horrendously bloated on the first database, so that
many more pages have to be touched to get the same number of tuples.
This would likely indicate an improper autovacuum configuration.

2. You failed to account for caching effects, ie the first example
is being run "cold" and has to actually read everything from disk,
whereas the second example has everything it needs already in RAM.
In that case the speed differential is quite illusory.

3. The HashAggregate would likely spit out the rows in a completely
different order than it received them.  If scanning large_table_b in
the order of IX_large_table_b_SigId happens to yield field_b values
that are very well ordered, it's possible that locality of access in
the other indexscans would be enough better in the second plan to
account for the speedup.  This seems the least likely theory, though.

BTW, how come is it that "SELECT large_table_b.field_b FROM 
large_table_b WHERE field_a = 2673056" produces no duplicate field_b
values?  Is that just luck?  Is there a unique constraint on the table
that implies it will happen?

			regards, tom lane

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


[Postgresql General]     [Postgresql PHP]     [PHP Users]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Yosemite]

  Powered by Linux