(now that my test went through, here is the question :) ) Dear Community, We are using PostgreSQL proudly for quite a long time, but now we are facing an interesting problem. Query plan seems to depend on how long the IN() clause is. explain analyze select p.product_id from product p left join infx.infx_product i on p.external_id = i.external_id where p.product_id in (7905, 7915, 7919, 7817, 8200, 7907, 7909, 9379, 9375, 9368, 9384, 9930, 9928, 9927, 9929, 9925, 9931, 9922, 7885, 9705, 8201, 7921); ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join (cost=40.52..108603.02 rows=11287 width=4) (actual time=1.187..33.484 rows=4882 loops=1) -> Seq Scan on product p (cost=0.00..577.41 rows=22 width=18) (actual time=1.012..5.144 rows=22 loops=1) Filter: (product_id = ANY ('{7905,7915,7919,7817,8200,7907,7909,9379,9375,9368,9384,9930,9928,9927,9929,9925,9931,9922,7885,9705,8201,7921}'::integer[])) -> Bitmap Heap Scan on infx_product i (cost=40.52..4890.70 rows=1564 width=15) (actual time=0.107..0.563 rows=222 loops=22) Recheck Cond: ((p.external_id)::text = (i.external_id)::text) -> Bitmap Index Scan on infx_product_full_external_id_key (cost=0.00..40.13 rows=1564 width=0) (actual time=0.091..0.091 rows=222 loops=22) Index Cond: ((p.external_id)::text = (i.external_id)::text) Total runtime: 41.470 ms (8 rows) Nice. But: explain analyze select p.product_id from product p left join infx.infx_product i on p.external_id = i.external_id where p.product_id in (7905, 7915, 7919, 7817, 8200, 7907, 7909, 9379, 9375, 9368, 9384, 9930, 9928, 9927, 9929, 9925, 9931, 9922, 7885, 9705, 8201, 7921,1,1,1,1,1,1); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Hash Left Join (cost=127157.21..128199.91 rows=14365 width=4) (actual time=11508.623..11518.198 rows=4882 loops=1) Hash Cond: ((p.external_id)::text = (i.external_id)::text) -> Bitmap Heap Scan on product p (cost=103.25..187.88 rows=28 width=18) (actual time=0.099..0.161 rows=22 loops=1) Recheck Cond: (product_id = ANY ('{7905,7915,7919,7817,8200,7907,7909,9379,9375,9368,9384,9930,9928,9927,9929,9925,9931,9922,7885,9705,8201,7921,1,1,1,1,1,1}'::integer[])) -> Bitmap Index Scan on pk_product (cost=0.00..103.24 rows=28 width=0) (actual time=0.086..0.086 rows=22 loops=1) Index Cond: (product_id = ANY ('{7905,7915,7919,7817,8200,7907,7909,9379,9375,9368,9384,9930,9928,9927,9929,9925,9931,9922,7885,9705,8201,7921,1,1,1,1,1,1}'::integer[])) -> Hash (cost=100040.65..100040.65 rows=2161065 width=15) (actual time=11505.578..11505.578 rows=2161065 loops=1) -> Seq Scan on infx_product i (cost=0.00..100040.65 rows=2161065 width=15) (actual time=0.074..6921.127 rows=2161065 loops=1) Total runtime: 11543.758 ms (9 rows) Another try: necosgi=# set enable_hashjoin=off; SET necosgi=# explain analyze select p.product_id from product p left join infx.infx_product i on p.external_id = i.external_id where p.product_id in (7905, 7915, 7919, 7817, 8200, 7907, 7909, 9379, 9375, 9368, 9384, 9930, 9928, 9927, 9929, 9925, 9931, 9922, 7885, 9705, 8201, 7921,1,1,1,1,1,1); ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join (cost=40.42..136685.07 rows=14365 width=4) (actual time=1.308..33.897 rows=4882 loops=1) -> Seq Scan on product p (cost=0.00..634.50 rows=28 width=18) (actual time=1.135..5.747 rows=22 loops=1) Filter: (product_id = ANY ('{7905,7915,7919,7817,8200,7907,7909,9379,9375,9368,9384,9930,9928,9927,9929,9925,9931,9922,7885,9705,8201,7921,1,1,1,1,1,1}'::integer[])) -> Bitmap Heap Scan on infx_product i (cost=40.42..4839.40 rows=1564 width=15) (actual time=0.096..0.553 rows=222 loops=22) Recheck Cond: ((p.external_id)::text = (i.external_id)::text) -> Bitmap Index Scan on infx_product_full_external_id_key (cost=0.00..40.03 rows=1564 width=0) (actual time=0.080..0.080 rows=222 loops=22) Index Cond: ((p.external_id)::text = (i.external_id)::text) Total runtime: 41.961 ms (8 rows) It looks like the maximum cost of the nested loop is higher than the maximum cost of hashjoin, that's why the planner chooses hashjoin. Table was analyzed, index was reindexed. This behaviour is always reproducible. Questions: - how could I avoid full table scan - how can I advise to use the index? - how could I advise planner to better estimate the (much lower) cost of the nested loop? Another info: if I put more 1's in the query, the planner will use mergejoins... bahh :) Any help/question/suggestion is welcome! Best regards, Akos -- Sent via pgsql-performance mailing list (pgsql-performance@xxxxxxxxxxxxxx) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance