Re: Query performance going from Oracle to Postgres

From: Peter Geoghegan <pg(at)bowt(dot)ie>
To: "Dirschel, Steve" <steve(dot)dirschel(at)thomsonreuters(dot)com>
Cc: "pgsql-general(at)lists(dot)postgresql(dot)org" <pgsql-general(at)lists(dot)postgresql(dot)org>, "Wong, Kam Fook (TR Technology)" <kamfook(dot)wong(at)thomsonreuters(dot)com>
Subject: Re: Query performance going from Oracle to Postgres
Date: 2023-09-07 03:07:47
Message-ID: CAH2-Wz=BP65O2_bNqeaGFiCZmYGEvcjtmf4sLJM5TXnbK38FRQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Wed, Sep 6, 2023 at 1:07 PM Dirschel, Steve
<steve(dot)dirschel(at)thomsonreuters(dot)com> wrote:
> Oracle will find the same 332 rows using the same index but in Oracle it only does 20 logical reads. I thought maybe the index was fragmented so I reindexed that index:

It seems likely that the problem here is that some of the predicates
appear as so-called "Filter:" conditions, as opposed to true index
quals. For reasons that aren't particularly fundamental, Postgres
B-Trees cannot push down != (or <>) to the index level. Strangely
enough, this is possible with IS NOT NULL. I'm working to improve
things in this area.

That difference is easy to see in the following example. The first
query does far fewer buffer accesses than the. second query, despite
being very similar:

regression=# explain (analyze, buffers) select * from multi_test where
a = 1 and b is not null;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using multi_test_idx on multi_test (cost=0.29..50.10
rows=2191 width=8) (actual time=0.095..0.100 rows=14 loops=1)
Index Cond: ((a = 1) AND (b IS NOT NULL))
Heap Fetches: 0
Buffers: shared hit=3
Planning Time: 0.056 ms
Execution Time: 0.145 ms
(6 rows)

regression=# explain (analyze, buffers) select * from multi_test where
a = 1 and b != 42;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using multi_test_idx on multi_test
(cost=0.29..222.57 rows=2191 width=8) (actual time=0.087..2.982
rows=14 loops=1)
Index Cond: (a = 1)
Filter: (b <> 42)
Rows Removed by Filter: 10000
Heap Fetches: 0
Buffers: shared hit=11
Planning Time: 0.076 ms
Execution Time: 3.204 ms
(8 rows)

(There are lots of index tuples matching (a, b) = "(1, NULL)" here, you see.)

--
Peter Geoghegan

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Daniel Gustafsson 2023-09-07 07:22:15 Re: listening on an address other than 'localhost'?
Previous Message David Rowley 2023-09-07 02:28:17 Re: Query performance going from Oracle to Postgres