Index-only scan not working when IN clause has 2 or more values - Mailing list pgsql-general

From Anna B.
Subject Index-only scan not working when IN clause has 2 or more values
Date
Msg-id 1669301102.998685549@f535.i.mail.ru
Whole thread Raw
Responses Re: Index-only scan not working when IN clause has 2 or more values  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general
 
Hi all,
 
CREATE TABLE transaction
(
    client_id     decimal(18, 0) NOT NULL,
    trans_dttm    timestamp,
    division_code varchar(255),
    ...
)
 
One row size = approx 2Kb.
 
Usually table is searched by client_id and trans_dttm, but sometimes also by division_code, so:
 
create index "ix-transaction-client-trans_dttm-division"
    on transaction (client_id,
                    trans_dttm desc,
                    division_code);
 
Query:
 
EXPLAIN (ANALYZE, BUFFERS)
select *
from transaction
where client_id = 123456
  and (trans_dttm between TO_DATE('01.01.2020', 'dd.mm.yyyy') and TO_DATE('31.12.2022', 'dd.mm.yyyy'))
  and (division_code in
       ('not_existing_code1', 'not_existing_code2'))
order by trans_dttm desc
limit 50 offset 0;
 
Result:
 
Limit  (cost=0.57..14874.50 rows=50 width=2675) (actual time=703291.836..703291.845 rows=0 loops=1)
  Buffers: shared hit=7981349 read=2078884
  I/O Timings: read=683180.769
"  ->  Index Scan using ""ix-transaction-client-trans_dttm-division"" on transaction  (cost=0.57..8350814.66 rows=28072 width=2675) (actual time=703291.834..703291.835 rows=0 loops=1)"
"        Index Cond: ((client_id = '123456'::numeric) AND (trans_dttm >= to_date('01.01.2020'::text, 'dd.mm.yyyy'::text)) AND (trans_dttm <= to_date('31.12.2022'::text, 'dd.mm.yyyy'::text)))"
"        Filter: ((division_code)::text = ANY ('{not_existing_code1,not_existing_code2}'::text[]))"
        Rows Removed by Filter: 10000000
        Buffers: shared hit=7981349 read=2078884
        I/O Timings: read=683180.769
Planning Time: 0.258 ms
Execution Time: 703291.901 ms
 
In case when only one division_code passed: division_code in ('not_existing_code1'), the result is much better:
 
Limit  (cost=0.57..810.34 rows=50 width=2675) (actual time=1479.254..1479.257 rows=0 loops=1)
  Buffers: shared read=60245
  I/O Timings: read=231.032
"  ->  Index Scan using ""ix-transaction-client-trans_dttm-division"" on transaction  (cost=0.57..227318.91 rows=14036 width=2675) (actual time=1479.251..1479.253 rows=0 loops=1)"
"        Index Cond: ((client_id = '123456'::numeric) AND (trans_dttm >= to_date('01.01.2020'::text, 'dd.mm.yyyy'::text)) AND (trans_dttm <= to_date('31.12.2022'::text, 'dd.mm.yyyy'::text)) AND ((division_code)::text = 'not_existing_code1'::text))"
        Buffers: shared read=60245
        I/O Timings: read=231.032
Planning Time: 1.031 ms
Execution Time: 1479.342 ms
 
Thanks in advance,
Dmitry
 
 

pgsql-general by date:

Previous
From: Rama Krishnan
Date:
Subject: How to select unique records in PostgreSQL
Next
From: Kirk Wolak
Date:
Subject: Re: About row locking ordering