Hello all,
We're stuck at a wrong plan that the planner insists on.(pg 14.2)
It's an aggregation over a single table.
The planner always goes for an extra scan over a partial index.
We have set statistics on the relevant columns to the max of 10000 and could not get correct row estimates. None of the cost* settings helped too.
Disabling bitmapscan below brings up the correct plan. Do we have another option here ?
Maybe it is a more general question of what to do when the statistics samples cannot get the right numbers?
Thank you in advance for your help,
Rado
Here are the details:
See the partial index that matches one of the query where clauses :
"transaction_events_0100_0200_merchant_id_id_idx" btree (merchant_id, id) WHERE (event_type::text = ANY (ARRAY['REFUND'::character varying::text, 'CHARGE_BACK'::character varying::text])) AND (current_status_id <> ALL (ARRAY[24, 10]))
the distribution of event_type is
count | event_type
----------+-------------
14908 | CHARGE_BACK
134007 | REFUND
99846581 | PAYOUT
(3 rows)
----------+-------------
14908 | CHARGE_BACK
134007 | REFUND
99846581 | PAYOUT
(3 rows)
*** The table:
test=# \d+ transaction_events_0100_0200
Table "public.transaction_events_0100_0200"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
----------------------------+-----------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
id | bigint | | not null | | plain | | |
transaction_id | bigint | | | | plain | | 10000 |
event_type | character varying(255) | | | | extended | | 10000 |
event_amount | numeric(12,2) | | | | main | | |
current_status_id | integer | | | | plain | | 10000 |
payout_due_date | date | | | | plain | | |
actual_payout_date | date | | | | plain | | |
current_payout_event_id | integer | | | | plain | | |
created_at | timestamp without time zone | | not null | | plain | | |
updated_at | timestamp without time zone | | not null | | plain | | |
installment_number | integer | | | | plain | | |
installments_count | integer | | | | plain | | |
fixed_fee | numeric(12,2) | | | | main | | |
acceleration_fee | numeric(12,2) | | | | main | | |
processing_fee | numeric(12,2) | | | | main | | |
origin_event_id | bigint | | | | plain | | |
destination_event_id | bigint | | | | plain | | |
payout_deduct_status | character varying | | | | extended | | |
merchant_id | integer | | not null | | plain | | 1000 |
current_merchant_payout_id | bigint | | | | plain | | |
Indexes:
"transaction_events_0100_0200_pkey" PRIMARY KEY, btree (id)
"transaction_events_0100_0200_current_status_id_transaction__idx" btree (current_status_id, transaction_id) WHERE current_status_id <> ALL (ARRAY[24, 10])
"transaction_events_0100_0200_merchant_id_id_idx" btree (merchant_id, id) WHERE (event_type::text = ANY (ARRAY['REFUND'::character varying::text, 'CHARGE_BACK'::character varying::text])) AND (current_status_id <> ALL (ARRAY[24, 10]))
"transaction_events_0100_0200_merchant_id_transaction_id_idx" btree (merchant_id, transaction_id) WHERE current_status_id <> ALL (ARRAY[24, 10])
"transaction_events_0100_0200_transaction_id_idx" btree (transaction_id) WITH (fillfactor='100')
"transaction_events_0100_0200_transaction_id_idx1" btree (transaction_id) WHERE event_type::text = 'CHARGE_BACK'::text AND payout_deduct_status::text = 'PENDING'::text
Table "public.transaction_events_0100_0200"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
----------------------------+-----------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
id | bigint | | not null | | plain | | |
transaction_id | bigint | | | | plain | | 10000 |
event_type | character varying(255) | | | | extended | | 10000 |
event_amount | numeric(12,2) | | | | main | | |
current_status_id | integer | | | | plain | | 10000 |
payout_due_date | date | | | | plain | | |
actual_payout_date | date | | | | plain | | |
current_payout_event_id | integer | | | | plain | | |
created_at | timestamp without time zone | | not null | | plain | | |
updated_at | timestamp without time zone | | not null | | plain | | |
installment_number | integer | | | | plain | | |
installments_count | integer | | | | plain | | |
fixed_fee | numeric(12,2) | | | | main | | |
acceleration_fee | numeric(12,2) | | | | main | | |
processing_fee | numeric(12,2) | | | | main | | |
origin_event_id | bigint | | | | plain | | |
destination_event_id | bigint | | | | plain | | |
payout_deduct_status | character varying | | | | extended | | |
merchant_id | integer | | not null | | plain | | 1000 |
current_merchant_payout_id | bigint | | | | plain | | |
Indexes:
"transaction_events_0100_0200_pkey" PRIMARY KEY, btree (id)
"transaction_events_0100_0200_current_status_id_transaction__idx" btree (current_status_id, transaction_id) WHERE current_status_id <> ALL (ARRAY[24, 10])
"transaction_events_0100_0200_merchant_id_id_idx" btree (merchant_id, id) WHERE (event_type::text = ANY (ARRAY['REFUND'::character varying::text, 'CHARGE_BACK'::character varying::text])) AND (current_status_id <> ALL (ARRAY[24, 10]))
"transaction_events_0100_0200_merchant_id_transaction_id_idx" btree (merchant_id, transaction_id) WHERE current_status_id <> ALL (ARRAY[24, 10])
"transaction_events_0100_0200_transaction_id_idx" btree (transaction_id) WITH (fillfactor='100')
"transaction_events_0100_0200_transaction_id_idx1" btree (transaction_id) WHERE event_type::text = 'CHARGE_BACK'::text AND payout_deduct_status::text = 'PENDING'::text
*** The query:
SELECT public.transaction_events_0100_0200.transaction_id,
SUM(public.transaction_events_0100_0200.event_amount) AS amount
FROM public.transaction_events_0100_0200
WHERE public.transaction_events_0100_0200.transaction_id = ANY('{2735975647,...,2697582948}')
AND public.transaction_events_0100_0200.event_type IN ('REFUND', 'CHARGE_BACK')
AND public.transaction_events_0100_0200.current_status_id IN (11,15,67)
GROUP BY public.transaction_events_0100_0200.transaction_id;
SUM(public.transaction_events_0100_0200.event_amount) AS amount
FROM public.transaction_events_0100_0200
WHERE public.transaction_events_0100_0200.transaction_id = ANY('{2735975647,...,2697582948}')
AND public.transaction_events_0100_0200.event_type IN ('REFUND', 'CHARGE_BACK')
AND public.transaction_events_0100_0200.current_status_id IN (11,15,67)
GROUP BY public.transaction_events_0100_0200.transaction_id;
*** The executions:
GroupAggregate (cost=202.67..202.69 rows=1 width=40) (actual time=56.197..56.198 rows=0 loops=1)
Group Key: transaction_id
-> Sort (cost=202.67..202.67 rows=1 width=14) (actual time=56.194..56.196 rows=0 loops=1)
Sort Key: transaction_id
Sort Method: quicksort Memory: 25kB
-> Bitmap Heap Scan on transaction_events_0100_0200 (cost=198.64..202.66 rows=1 width=14) (actual time=56.186..56.187 rows=0 loops=1)
Recheck Cond: (((event_type)::text = ANY ('{REFUND,CHARGE_BACK}'::text[])) AND (current_status_id <> ALL ('{24,10}'::integer[])) AND (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[])))
Filter: (current_status_id = ANY ('{11,15,67}'::integer[]))
-> BitmapAnd (cost=198.54..198.54 rows=1 width=0) (actual time=55.345..55.346 rows=0 loops=1)
-> Bitmap Index Scan on transaction_events_0100_0200_merchant_id_id_idx (cost=0.00..10.71 rows=458 width=0) (actual time=50.530..50.531 rows=148279 loops=1)
-> Bitmap Index Scan on transaction_events_0100_0200_transaction_id_idx (cost=0.00..187.58 rows=44 width=0) (actual time=0.071..0.071 rows=0 loops=1)
Index Cond: (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[]))
Planning Time: 1.517 ms
Execution Time: 56.298 ms
(14 rows)
Time: 58.636 ms
test=# set enable_bitmapscan to off;
SET
Time: 0.504 ms
test=# \i q221.sql
QUERY PLAN ----------------------------------------------------------------------------------------------------
Group Key: transaction_id
-> Sort (cost=202.67..202.67 rows=1 width=14) (actual time=56.194..56.196 rows=0 loops=1)
Sort Key: transaction_id
Sort Method: quicksort Memory: 25kB
-> Bitmap Heap Scan on transaction_events_0100_0200 (cost=198.64..202.66 rows=1 width=14) (actual time=56.186..56.187 rows=0 loops=1)
Recheck Cond: (((event_type)::text = ANY ('{REFUND,CHARGE_BACK}'::text[])) AND (current_status_id <> ALL ('{24,10}'::integer[])) AND (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[])))
Filter: (current_status_id = ANY ('{11,15,67}'::integer[]))
-> BitmapAnd (cost=198.54..198.54 rows=1 width=0) (actual time=55.345..55.346 rows=0 loops=1)
-> Bitmap Index Scan on transaction_events_0100_0200_merchant_id_id_idx (cost=0.00..10.71 rows=458 width=0) (actual time=50.530..50.531 rows=148279 loops=1)
-> Bitmap Index Scan on transaction_events_0100_0200_transaction_id_idx (cost=0.00..187.58 rows=44 width=0) (actual time=0.071..0.071 rows=0 loops=1)
Index Cond: (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[]))
Planning Time: 1.517 ms
Execution Time: 56.298 ms
(14 rows)
Time: 58.636 ms
test=# set enable_bitmapscan to off;
SET
Time: 0.504 ms
test=# \i q221.sql
QUERY PLAN ----------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.57..228.43 rows=1 width=40) (actual time=0.238..0.240 rows=0 loops=1)
Group Key: transaction_id
-> Index Scan using transaction_events_0100_0200_transaction_id_idx on transaction_events_0100_0200 (cost=0.57..228.41 rows=1 width=14) (actual time=0.235..0.236 rows=0 loops=1)
Index Cond: (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[]))
Filter: (((event_type)::text = ANY ('{REFUND,CHARGE_BACK}'::text[])) AND (current_status_id = ANY ('{11,15,67}'::integer[])))
Settings: enable_bitmapscan = 'off'
Planning Time: 1.204 ms
Execution Time: 0.312 ms
(8 rows)
Group Key: transaction_id
-> Index Scan using transaction_events_0100_0200_transaction_id_idx on transaction_events_0100_0200 (cost=0.57..228.41 rows=1 width=14) (actual time=0.235..0.236 rows=0 loops=1)
Index Cond: (transaction_id = ANY ('{2735975647,...,2697582948}'::bigint[]))
Filter: (((event_type)::text = ANY ('{REFUND,CHARGE_BACK}'::text[])) AND (current_status_id = ANY ('{11,15,67}'::integer[])))
Settings: enable_bitmapscan = 'off'
Planning Time: 1.204 ms
Execution Time: 0.312 ms
(8 rows)