Re: Index scan is not pushed down to union all subquery

From: Marian Wendt <marian(dot)wendt(at)yahoo(dot)com>
To: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: Re: Index scan is not pushed down to union all subquery
Date: 2023-10-05 09:13:23
Message-ID: 61de2059-b56b-45f4-98db-a5d9b982fa4b@yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

> Hi,
>
> Is it intended that indexes are not pushed down to union all
> subqueries if even a single select contains a where clause? Is this
> just not implemented, is it impossible to implement or am I doing
> something wrong?
>
> The following query does a SeqScan for "bikes" and "cars" tables even
> though IndexScan on their column "dealer_name" would be a magnitude
> faster. (Schema with sample data at the bottom of this mail)
>
> WITH
> targets as (
> select 'bike' vehicle, id, dealer_name FROM bikes WHERE frame_size = 52
> union all
> select 'car' vehicle, id, dealer_name FROM cars
> -- In the real use case I have here dozens of tables
> )
> SELECT
> dealers.name dealer,
> targets.vehicle,
> targets.id
> FROM
> dealers
> JOIN targets
> ON dealers.name = targets.dealer_name
> WHERE dealers.id in (54,12,456,315,468)
>
>
> If the WHERE clause from the "bikes" subquery is removed then first
> Index Scan on dealers_pk is made and then Bitmap Index Scans on
> "bikes" and "cars" table using indexes on "dealer_name" columns.
>
>
> ---------------------------------------------------------------
> -- Available also at:https://www.db-fiddle.com/f/cEXt8HXSaQzsQ2yBDA2Z4H/7
> CREATE TABLE dealers AS
> SELECT
> id,
> (SELECT string_agg(CHR(65+(random() * 25)::integer), '') FROM
> generate_series(1, 4) WHERE id>0) name
> FROM generate_series(1, 1000) AS id
> ;
> ALTER TABLE dealers ADD primary key (id);
> CREATE INDEX ON dealers(name);
>
>
> CREATE TABLE bikes AS
> SELECT
> generate_series AS id,
> (SELECT name FROM dealers WHERE dealers.id = (SELECT
> (random()*1000)::int WHERE generate_series>0)) AS dealer_name,
> (random()*12+50)::int as frame_size
> FROM generate_series(1, 100000);
> ALTER TABLE bikes ADD primary key (id);
> CREATE INDEX ON bikes(dealer_name);
>
>
> CREATE TABLE cars AS
> SELECT
> generate_series as id,
> (SELECT name FROM dealers WHERE dealers.id = (SELECT
> (random()*1000)::int WHERE generate_series>0)) AS dealer_name,
> (random()*7+14)::int as wheel_size
> FROM generate_series(1, 100000);
> ALTER TABLE cars ADD primary key (id);
> CREATE INDEX ON cars(dealer_name);
>
>
> ANALYZE;
>
>
> --
> - Lauri
>
>

With an INNER JOIN, both tables must be fully checked/matched (check
using EXPLAIN ANALYSIS -> HashJoin), so the index cannot be used here.
--
regards, marian wendt

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Marian Wendt 2023-10-05 09:20:10 Re: Index scan is not pushed down to union all subquery
Previous Message Abhishek Bhola 2023-10-05 07:09:41 Re: pgBackRest for a 50 TB database