Search Postgresql Archives

Problem with planner choosing nested loop

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

 



Hello,

I was trying to optimize a slow query in database running 8.3.1. It turned out that planner is choosing nested loop join resulting in multiple sequential scans over the long table. Here is a simplified database schema, consisting of two tables:

    CREATE TABLE bar (
        bar_id integer PRIMARY KEY,
        bar_a integer,
        bar_b integer,
        bar_c integer,
        bar_d integer,
        bar_e integer,
        bar_f integer,
        bar_g integer,
       bar_h integer
    );

    CREATE TABLE foo (
        foo_a  integer,
        foo_b  integer,
        foo_c  integer,
        bar_id integer
    );

Table "bar" has 16805 records and table "foo" is fairly big, having over 6 million records. default_statistics_target is set to 1000 (in fact, I tried many values from 100 to 1000 but it did not help), VACUUM ANALYZE was executed before running test queries.

Running this query:
    EXPLAIN ANALYZE SELECT foo_b, SUM(foo_c)
    FROM foo JOIN bar USING (bar_id) WHERE foo_a = 1001
    AND bar_h = 1821 AND bar_c = 519 GROUP BY foo_b;

produces this plan:
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=110916.41..110916.42 rows=1 width=8) (actual time=20547.433..20547.433 rows=1 loops=1) -> Nested Loop (cost=0.00..110916.40 rows=1 width=8) (actual time=17952.622..20547.175 rows=59 loops=1)
         Join Filter: (foo.bar_id = bar.bar_id)
-> Seq Scan on bar (cost=0.00..393.07 rows=1 width=4) (actual time=0.098..3.561 rows=24 loops=1)
               Filter: ((bar_h = 1821) AND (bar_c = 519))
-> Seq Scan on foo (cost=0.00..110510.89 rows=995 width=12) (actual time=0.957..855.366 rows=1369 loops=24)
               Filter: (foo.foo_a = 1001)
 Total runtime: 20547.518 ms

The problem is that 6+ million rows table "foo" is scanned 24 times:
     Seq Scan on foo  (... loops=24)

If I try to disable nested loops using set enable_nestloop=off, the plan is just fine: QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=110907.72..110907.73 rows=1 width=8) (actual time=889.239..889.240 rows=1 loops=1) -> Hash Join (cost=393.09..110907.72 rows=1 width=8) (actual time=17.825..889.065 rows=59 loops=1)
         Hash Cond: (foo.bar_id = bar.bar_id)
-> Seq Scan on foo (cost=0.00..110510.89 rows=995 width=12) (actual time=2.309..883.841 rows=1369 loops=1)
               Filter: (foo_a = 1001)
-> Hash (cost=393.07..393.07 rows=1 width=4) (actual time=4.168..4.168 rows=24 loops=1) -> Seq Scan on bar (cost=0.00..393.07 rows=1 width=4) (actual time=0.118..4.141 rows=24 loops=1)
                     Filter: ((bar_h = 1821) AND (bar_c = 519))
 Total runtime: 889.329 ms

Unfortunately, I cannot disable nested loops because if I do, some other queries degrade miserably, and disabling nested loops just for this query is not an option.
I think the problem is caused by wrong estimate for the table "bar":

Seq Scan on bar (cost=0.00..393.07 rows=1 width=4) (actual time=0.098..3.561 rows=24 loops=1)

but so far, I have no idea how it could be fixed. As I've said, I tried increasing statistics_target to the max value (1000) but it did not help. The test database dump (6.3 Mb download) is available at http://216.159.242.194/test_dump.sql.bz2

Alex

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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux