Re: LIKE foo% optimization easily defeated by OR?

From: Alexander Korotkov <a(dot)korotkov(at)postgrespro(dot)ru>
To: Greg Stark <stark(at)mit(dot)edu>
Cc: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: LIKE foo% optimization easily defeated by OR?
Date: 2018-01-03 22:34:44
Message-ID: CAPpHfdus0ZrviDqTymXnOFV6iyaQd0trLekLTvEJZQMQgUu3gg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi, Greg!

On Thu, Jan 4, 2018 at 12:57 AM, Greg Stark <stark(at)mit(dot)edu> wrote:

> Our database has a query that looks like this -- note the OR between a
> simple equality qual and a LIKE qual:
>
> => explain SELECT 1 AS one FROM "redirect_routes" WHERE
> redirect_routes.path = 'foobar' OR redirect_routes.path LIKE
> 'foobar/%';
> QUERY PLAN
> ------------------------------------------------------------
> -----------------------
> Seq Scan on redirect_routes (cost=0.00..1776.23 rows=5 width=4)
> Filter: (((path)::text = 'foobar'::text) OR ((path)::text ~~
> 'foobar/%'::text))
> (2 rows)
>
>
> The database uses a sequential scan even though both of the sides of
> that OR have valid indexes that can satisfy them (and for much lower
> costs):
>
> => explain SELECT 1 AS one FROM "redirect_routes" WHERE
> redirect_routes.path = 'foobar' ;
> QUERY PLAN
> ------------------------------------------------------------
> ---------------------------------------------------------------
> Index Only Scan using index_redirect_routes_on_path_text_pattern_ops
> on redirect_routes (cost=0.41..4.43 rows=1 width=4)
> Index Cond: (path = 'foobar'::text)
> (2 rows)
>
> => explain SELECT 1 AS one FROM "redirect_routes" WHERE
> redirect_routes.path LIKE 'foobar/%';
> QUERY PLAN
> ------------------------------------------------------------
> ---------------------------------------------------------------
> Index Only Scan using index_redirect_routes_on_path_text_pattern_ops
> on redirect_routes (cost=0.41..4.44 rows=4 width=4)
> Index Cond: ((path ~>=~ 'foobar/'::text) AND (path ~<~ 'foobar0'::text))
> Filter: ((path)::text ~~ 'foobar/%'::text)
> (3 rows)
>
>
> I'm guessing the LIKE optimization isn't clever enough to kick in when
> it's buried under an OR? Does it only kick in at the top level of the
> quals?

I've checked similar case on database with PostgreSQL mailing lists. It
works for me.

# explain select * from messages where level = 1 or author like 'Greg%';
QUERY PLAN
-------------------------------------------------------------------------------------------
Bitmap Heap Scan on messages (cost=80.01..5967.43 rows=3933 width=1343)
Recheck Cond: ((level = 1) OR (author ~~ 'Greg%'::text))
Filter: ((level = 1) OR (author ~~ 'Greg%'::text))
-> BitmapOr (cost=80.01..80.01 rows=3897 width=0)
-> Bitmap Index Scan on messages_level_idx (cost=0.00..73.17
rows=3851 width=0)
Index Cond: (level = 1)
-> Bitmap Index Scan on messages_author_idx (cost=0.00..4.87
rows=46 width=0)
Index Cond: ((author ~>=~ 'Greg'::text) AND (author ~<~
'Greh'::text))
(8 rows)

So, I think in principle optimizer is capable to handle such kind of
queries (pgsql 9.6.6).
Did you try setting enable_seqscan = off? Probably, something is wrong
with costing in this case...

------
Alexander Korotkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Greg Stark 2018-01-03 22:55:41 Re: LIKE foo% optimization easily defeated by OR?
Previous Message Dagfinn Ilmari =?utf-8?Q?Manns=C3=A5ker?= 2018-01-03 22:28:28 Re: [PATCH] Comment typo in get_collation_name() comment