Hi Performance Guys, I hope you can help me. I am joining two tables, that have a foreign key relationship. So I expect the optimizer to estimate the number of the resulting rows to be the same as the number of the returned rows of one of
the tables. But the estimate is way too low. I have built a test case, where the problem is easily to be seen. Testcase: create table fact (low_card integer, anydata1 integer, anydata2 integer); insert into fact (low_card, anydata1, anydata2) select floor(random()*3+1),floor(random()*1000+1),floor(random()*100+1) from generate_series(1,10000); -- create a smaller table with only unique values to be referenced by foreign key create table dim as (select distinct low_card, anydata1, anydata2 from fact); create unique index on dim (low_card, anydata1, anydata2); alter table fact add constraint fk foreign key (low_card, anydata1, anydata2) references dim (low_card, anydata1, anydata2); analyze fact; analyze dim; And here comes the query: explain analyze select count(*) from fact inner join dim on (fact.low_card=dim.low_card and fact.anydata1=dim.anydata1 and fact.anydata2=dim.anydata2) where fact.low_card=1; Aggregate (cost=424.11..424.12 rows=1 width=8) (actual time=7.899..7.903 rows=1 loops=1) -> Hash Join (cost=226.27..423.82 rows=115 width=0) (actual time=3.150..7.511 rows=3344 loops=1)
<=========== With the FK, the estimation should be 3344, but it is 115 rows Hash Cond: ((fact.anydata1 = dim.anydata1) AND (fact.anydata2 = dim.anydata2))
-> Seq Scan on fact (cost=0.00..180.00 rows=3344 width=12) (actual time=0.025..2.289 rows=3344 loops=1)
Filter: (low_card = 1) Rows Removed by Filter: 6656 -> Hash (cost=176.89..176.89 rows=3292 width=12) (actual time=3.105..3.107 rows=3292 loops=1) Buckets: 4096 Batches: 1 Memory Usage: 174kB -> Seq Scan on dim (cost=0.00..176.89 rows=3292 width=12) (actual time=0.014..2.103 rows=3292 loops=1) Filter: (low_card = 1) Rows Removed by Filter: 6539 Planning Time: 0.619 ms Execution Time: 7.973 ms My problem is, that I am joining a lot more tables in reality and since the row estimates are so low, the optimizer goes for nested loops, leading to inacceptable execution times. Question: How can I get the optimizer to use the information about the foreign key relationship and get accurate estimates? Sigrid Ehrenreich |