> Csaba, please can you copy that data into fresh tables, re-ANALYZE and
> then re-post the EXPLAINs, with stats data.
Here you go, fresh experiment attached.
Cheers,
Csaba.
db=# \d temp_table_a
Table "public.temp_table_a"
Column | Type | Modifiers
--------+--------+-----------
a | bigint | not null
b | bigint | not null
Indexes:
"temp_pk_table_a" PRIMARY KEY, btree (a, b)
db=# \d temp_table_b1
Table "public.temp_table_b1"
Column | Type | Modifiers
--------+--------+-----------
b | bigint | not null
Indexes:
"temp_pk_table_b1" PRIMARY KEY, btree (b)
db=# \d temp_table_b2
Table "public.temp_table_b2"
Column | Type | Modifiers
--------+--------+-----------
b | bigint | not null
Indexes:
"temp_pk_table_b2" PRIMARY KEY, btree (b)
Foreign-key constraints:
"temp_fk_table_b2_b1" FOREIGN KEY (b) REFERENCES temp_table_b1(b)
db=# analyze verbose temp_table_a;
INFO: analyzing "public.temp_table_a"
INFO: "temp_table_a": scanned 3000 of 655299 pages, containing 1887000 live
rows and 0 dead rows; 3000 rows in sample, 412183071 estimated total rows
db=# analyze verbose temp_table_b1;
INFO: analyzing "public.temp_table_b1"
INFO: "temp_table_b1": scanned 3000 of 57285 pages, containing 2232000 live
rows and 0 dead rows; 3000 rows in sample, 42620040 estimated total rows
db=# analyze verbose temp_table_b2;
INFO: analyzing "public.temp_table_b2"
INFO: "temp_table_b2": scanned 57 of 57 pages, containing 41967 live rows and
0 dead rows; 3000 rows in sample, 41967 estimated total rows
db=# select * from pg_stats where tablename = 'temp_table_a';
schemaname | tablename | attname | null_frac | avg_width | n_distinct |
most_common_vals
| most_common_freqs
|
histogram_bounds |
correlation
------------+--------------+---------+-----------+-----------+------------+-------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+-------------
public | temp_table_a | a | 0 | 8 | 1261 |
{700004117,700022128,700002317,700009411,700023682,700006025,700002843,700014833,700006505,700008694}
|
{0.015,0.0116667,0.00966667,0.00966667,0.00966667,0.009,0.00866667,0.008,0.00766667,0.00766667}
|
{70010872,700000035,700003086,700005843,700008974,700011369,700013305,700015988,700019048,700022257,800003151}
| 0.850525
public | temp_table_a | b | 0 | 8 | -1 |
|
|
{41708986,700707712,803042997,7004741432,7007455842,7009719495,7013869874,7016501748,7019139288,7025078292,7037930133}
| 0.646759
db=# select * from pg_stats where tablename = 'temp_table_b1';
schemaname | tablename | attname | null_frac | avg_width | n_distinct |
most_common_vals | most_common_freqs |
histogram_bounds
| correlation
------------+---------------+---------+-----------+-----------+------------+------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------+-------------
public | temp_table_b1 | b | 0 | 8 | -1 |
| |
{41719236,801608645,7003211583,7007403678,7011591097,7016707278,7021089839,7025573684,7029316772,7033888226,8002470137}
| 0.343186
db=# select * from pg_stats where tablename = 'temp_table_b2';
schemaname | tablename | attname | null_frac | avg_width | n_distinct |
most_common_vals | most_common_freqs |
histogram_bounds
| correlation
------------+---------------+---------+-----------+-----------+------------+------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------+-------------
public | temp_table_b2 | b | 0 | 8 | -1 |
| |
{700533334,7000352893,7000357745,7000362304,7000367025,7000371629,7000376587,7000381229,7009567724,7023749432,7034300740}
| -0.216073
db=# prepare test_001(bigint) as
db-# SELECT tb.*
db-# FROM temp_table_a ta
db-# JOIN temp_table_b2 tb ON ta.b=tb.b
db-# WHERE ta.a = $1
db-# ORDER BY ta.a, ta.b
db-# limit 10;
db=# explain analyze execute test_001(31855344);
QUERY
PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=152569.69..152569.72 rows=10 width=24) (actual
time=581.776..581.776 rows=0 loops=1)
-> Sort (cost=152569.69..152569.78 rows=33 width=24) (actual
time=581.774..581.774 rows=0 loops=1)
Sort Key: ta.a, ta.b
-> Nested Loop (cost=0.00..152568.86 rows=33 width=24) (actual
time=581.763..581.763 rows=0 loops=1)
-> Seq Scan on temp_table_b2 tb (cost=0.00..476.67 rows=41967
width=8) (actual time=0.005..69.190 rows=41967 loops=1)
-> Index Scan using temp_pk_table_a on temp_table_a ta
(cost=0.00..3.61 rows=1 width=16) (actual time=0.009..0.009 rows=0 loops=41967)
Index Cond: ((ta.a = $1) AND (ta.b = "outer".b))
Total runtime: 581.844 ms
(8 rows)
db=# prepare test_002(bigint) as
db-# SELECT tb.*
db-# FROM temp_table_a ta
db-# JOIN temp_table_b1 tb ON ta.b=tb.b
db-# WHERE ta.a = $1
db-# ORDER BY ta.a, ta.b
db-# limit 10;
db=# explain analyze execute test_002(31855344);
QUERY
PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..471.24 rows=10 width=24) (actual time=0.036..0.036 rows=0
loops=1)
-> Nested Loop (cost=0.00..1592742.78 rows=33799 width=24) (actual
time=0.033..0.033 rows=0 loops=1)
-> Index Scan using temp_pk_table_a on temp_table_a ta
(cost=0.00..315266.89 rows=326870 width=16) (actual time=0.023..0.023 rows=0
loops=1)
Index Cond: (a = $1)
-> Index Scan using temp_pk_table_b1 on temp_table_b1 tb
(cost=0.00..3.90 rows=1 width=8) (never executed)
Index Cond: ("outer".b = tb.b)
Total runtime: 2.483 ms
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend