set column statistics to max does not help - Mailing list pgsql-general

From Radoslav Nedyalkov
Subject set column statistics to max does not help
Date
Msg-id CANhtRibBuXcDA05Ccf0VfejOgVaevzYf8mC-XdZa=+JVepJfag@mail.gmail.com
Whole thread Raw
List pgsql-general
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)

*** 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


*** 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;

*** 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                                                                                                                                           
----------------------------------------------------------------------------------------------------
 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)

pgsql-general by date:

Previous
From: Michael Lewis
Date:
Subject: Re: LwLocks contention
Next
From: raf
Date:
Subject: Re: Are stored procedures/triggers common in your industry