Thread: Optimizer : query rewrite and execution plan ?

Optimizer : query rewrite and execution plan ?

From
SURANTYN Jean François
Date:
Hi
 
I have discovered an issue on my Postgresql database recently installed : it seems that the optimizer can not, when possible, simplify and rewrite a simple query before running it. Here is a simple and reproducible example :
 
my_db=# create table test (n numeric);
CREATE
my_db=# insert into test values (1); --> run 10 times
INSERT
my_db=# insert into test values (0); --> run 10 times
INSERT
my_db=# select count(*) from test;
count
-------
20
(1 row)
my_db=# vacuum full analyze test;
VACUUM
my_db=# explain select * from test where n = 1;
QUERY PLAN
------------------------------------------------------
Seq Scan on test (cost=0.00..1.25 rows=10 width=9)
Filter: (n = 1::numeric)
(2 rows)
 
my_db=# explain select * from test where n = 1 and n = 1;
QUERY PLAN
-----------------------------------------------------
Seq Scan on test (cost=0.00..1.30 rows=5 width=9)
Filter: ((n = 1::numeric) AND (n = 1::numeric))
(2 rows)
 
In the first SELECT query (with "where n=1"), the estimated number of returned rows is correct (10), whereas in the second SELECT query (with "where n=1 and n=1"), the estimated number of returned rows is 5 (instead of 10 !)
So the optimizer has under-estimated the number of rows returned
That issue is very annoying because with generated SQL queries (from Business Objects for example) on big tables, it is possible that some queries have several times the same "where" condition ("where n=1 and n=1" for example), and as the optimizer is under-estimating the number of returned rows, some bad execution plans can be chosen (nested loops instead of hash joins for example)
 
Is the estimated number of returned rows directly linked to the decision of the optimizer to chose Hash Joins or Nested Loops in join queries ?
Is there a way for the Postgresql optimizer to be able to simplify and rewrite the SQL statements before running them ? Are there some parameters that could change the execution plans ?
 
Thanks by advance for your help
 
Jean-Francois SURANTYN
 

**********************************************************************

This email and any files transmitted with it are confidential and

intended solely for the use of the individual or entity to whom they

are addressed. If you have received this email in error please notify

the system manager.

 

Supermarchés MATCH, Société Par Actions Simplifiée au capital de 10 420 100 €, immatriculée au RCS de LILLE sous le Numéro B 785 480 351

Siège : 250, rue du Général de Gaulle - BP 201 - 59 561 LA MADELEINE Cedex

**********************************************************************

 

Re: Optimizer : query rewrite and execution plan ?

From
Richard Huxton
Date:
SURANTYN Jean François wrote:
> my_db=# explain select * from test where n = 1;

> my_db=# explain select * from test where n = 1 and n = 1;

> In the first SELECT query (with "where n=1"), the estimated number of
> returned rows is correct (10), whereas in the second SELECT query
> (with "where n=1 and n=1"), the estimated number of returned rows is
> 5 (instead of 10 !) So the optimizer has under-estimated the number
> of rows returned

That's because it's a badly composed query. The planner is guessing how
much overlap there would be between the two clauses. It's not exploring
the option that they are the same clause repeated.

> That issue is very annoying because with generated
> SQL queries (from Business Objects for example) on big tables, it is
> possible that some queries have several times the same "where"
> condition ("where n=1 and n=1" for example), and as the optimizer is
> under-estimating the number of returned rows, some bad execution
> plans can be chosen (nested loops instead of hash joins for example)

Sounds like your query-generator needs a bit of an improvement, from my end.

> Is the estimated number of returned rows directly linked to the
> decision of the optimizer to chose Hash Joins or Nested Loops in join
> queries ?

Yes, well the cost determines a plan and obviously number of rows
affects the cost.

> Is there a way for the Postgresql optimizer to be able to
> simplify and rewrite the SQL statements before running them ?

It does, just not this one. It spots things like a=b and b=c implies a=c
(for joins etc).

> Are
> there some parameters that could change the execution plans ?

Not really in this case.

The root of your problem is that you have a query with an irrelevant
clause (AND n=1) and you'd like the planner to notice that it's
irrelevant and remove it from the query. There are two problems with this:

1. It's only going to be possible in simple cases. It's unlikely the
planner would ever spot "n=2 AND n=(10/5)"
2. Even in the simple case you're going to waste time checking *every
query* to see if clauses could be eliminated.

Is there any way to improve your query generator?

--
  Richard Huxton
  Archonet Ltd

Re: Optimizer : query rewrite and execution plan ?

From
SURANTYN Jean François
Date:
Many thanks for your quick reply

In fact, that issue comes from a recent migration from Oracle to Postgresql, and even if some queries were not
optimizedby the past (example: where n=1 and n=1), Oracle was able to rewrite them and to "hide" the bad queries". But
nowthat we have migrated to Postgresql, we have discovered that some queries were indeed badly wroten 
I will tell to the developpers to try to optimize their queries for them to work efficiently on Postgresql

Thanks again for your help

Regards

Jean-Francois SURANTYN


-----Message d'origine-----
De : Richard Huxton [mailto:dev@archonet.com]
Envoyé : mercredi 6 février 2008 10:47
À : SURANTYN Jean François
Cc : pgsql-performance@postgresql.org
Objet : Re: [PERFORM] Optimizer : query rewrite and execution plan ?

SURANTYN Jean François wrote:
> my_db=# explain select * from test where n = 1;

> my_db=# explain select * from test where n = 1 and n = 1;

> In the first SELECT query (with "where n=1"), the estimated number of
> returned rows is correct (10), whereas in the second SELECT query
> (with "where n=1 and n=1"), the estimated number of returned rows is
> 5 (instead of 10 !) So the optimizer has under-estimated the number of
> rows returned

That's because it's a badly composed query. The planner is guessing how much overlap there would be between the two
clauses.It's not exploring the option that they are the same clause repeated. 

> That issue is very annoying because with generated SQL queries (from
> Business Objects for example) on big tables, it is possible that some
> queries have several times the same "where"
> condition ("where n=1 and n=1" for example), and as the optimizer is
> under-estimating the number of returned rows, some bad execution plans
> can be chosen (nested loops instead of hash joins for example)

Sounds like your query-generator needs a bit of an improvement, from my end.

> Is the estimated number of returned rows directly linked to the
> decision of the optimizer to chose Hash Joins or Nested Loops in join
> queries ?

Yes, well the cost determines a plan and obviously number of rows affects the cost.

> Is there a way for the Postgresql optimizer to be able to simplify and
> rewrite the SQL statements before running them ?

It does, just not this one. It spots things like a=b and b=c implies a=c (for joins etc).

> Are
> there some parameters that could change the execution plans ?

Not really in this case.

The root of your problem is that you have a query with an irrelevant clause (AND n=1) and you'd like the planner to
noticethat it's irrelevant and remove it from the query. There are two problems with this: 

1. It's only going to be possible in simple cases. It's unlikely the planner would ever spot "n=2 AND n=(10/5)"
2. Even in the simple case you're going to waste time checking *every
query* to see if clauses could be eliminated.

Is there any way to improve your query generator?

--
  Richard Huxton
  Archonet Ltd

**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

Supermarchés MATCH, Société Par Actions Simplifiée au capital de 10 420 100 €, immatriculée au RCS de LILLE sous le
NuméroB 785 480 351 
Siège : 250, rue du Général de Gaulle - BP 201 - 59 561 LA MADELEINE Cedex
**********************************************************************


Re: Optimizer : query rewrite and execution plan ?

From
Richard Huxton
Date:
SURANTYN Jean François wrote:
> Many thanks for your quick reply
>
> In fact, that issue comes from a recent migration from Oracle to
> Postgresql, and even if some queries were not optimized by the past
> (example: where n=1 and n=1), Oracle was able to rewrite them and to
> "hide" the bad queries". But now that we have migrated to Postgresql,
> we have discovered that some queries were indeed badly wroten I will
> tell to the developpers to try to optimize their queries for them to
> work efficiently on Postgresql

If nothing else it will help when / if you decide to use prepared
queries - there's no way to optimise "n=$1 or n=$2" at planning time.

--
  Richard Huxton
  Archonet Ltd

Re: Optimizer : query rewrite and execution plan ?

From
Simon Riggs
Date:
On Wed, 2008-02-06 at 09:42 +0100, SURANTYN Jean François wrote:

> That issue is very annoying because with generated SQL queries (from
> Business Objects for example) on big tables, it is possible that some
> queries have several times the same "where" condition ("where n=1 and
> n=1" for example), and as the optimizer is under-estimating the number
> of returned rows, some bad execution plans can be chosen (nested loops
> instead of hash joins for example)

I can see the annoyance there.

There's a balance in the planner between time spent to optimize the
query and time spent to correct mistakes. If we looked continually for
mistakes then planning time would increase for everybody that didn't
suffer from this problem.

Since the SQL is not your fault and difficult to control, it is an
argument in favour of an optional planner mode that would perform
additional checks for redundant clauses of various kinds. The default
for that would be "off" since most people don't suffer from this
problem. BO isn't the only SQL generating-client out there, so I think
this is a fairly wide problem.

--
  Simon Riggs
  2ndQuadrant  http://www.2ndQuadrant.com


Re: Optimizer : query rewrite and execution plan ?

From
Theo Kramer
Date:
On Wed, 2008-02-06 at 11:53 +0000, Simon Riggs wrote:
> On Wed, 2008-02-06 at 09:42 +0100, SURANTYN Jean François wrote:
>
> > That issue is very annoying because with generated SQL queries (from
> > Business Objects for example) on big tables, it is possible that some
> > queries have several times the same "where" condition ("where n=1 and
> > n=1" for example), and as the optimizer is under-estimating the number
> > of returned rows, some bad execution plans can be chosen (nested loops
> > instead of hash joins for example)
>
> I can see the annoyance there.
>
> There's a balance in the planner between time spent to optimize the
> query and time spent to correct mistakes. If we looked continually for
> mistakes then planning time would increase for everybody that didn't
> suffer from this problem.
>
> Since the SQL is not your fault and difficult to control, it is an
> argument in favour of an optional planner mode that would perform
> additional checks for redundant clauses of various kinds. The default
> for that would be "off" since most people don't suffer from this
> problem. BO isn't the only SQL generating-client out there, so I think
> this is a fairly wide problem.

I would have to disagree. I spend a lot of time writing code that
generates SQL from a business app and feel strongly that any
optimisation is my responsibility.

Having to re-configure PG to switch on a planner mode, as suggested
above, to address badly generated SQL is not a good idea.

This with experience on having to talk business application developers
through re-configuring a database.

--
Regards
Theo


Re: Optimizer : query rewrite and execution plan ?

From
"Roberts, Jon"
Date:
> > Since the SQL is not your fault and difficult to control, it is an
> > argument in favour of an optional planner mode that would perform
> > additional checks for redundant clauses of various kinds. The
default
> > for that would be "off" since most people don't suffer from this
> > problem. BO isn't the only SQL generating-client out there, so I
think
> > this is a fairly wide problem.
>
> I would have to disagree. I spend a lot of time writing code that
> generates SQL from a business app and feel strongly that any
> optimisation is my responsibility.
>

The point to a BI tool like BO is to abstract the data collection and do
it dynamically.  The SQL is built at run time because the tool is
designed to give the end user as much flexibility as the data structure
allows to query the data however they want.

It isn't feasible, possible, or recommended to rewrite all of the
possible generated SQL that could be designed at runtime by the tool.



Jon

Re: Optimizer : query rewrite and execution plan ?

From
Erik Jones
Date:
On Feb 6, 2008, at 7:35 AM, Roberts, Jon wrote:

>
>>> Since the SQL is not your fault and difficult to control, it is an
>>> argument in favour of an optional planner mode that would perform
>>> additional checks for redundant clauses of various kinds. The
> default
>>> for that would be "off" since most people don't suffer from this
>>> problem. BO isn't the only SQL generating-client out there, so I
> think
>>> this is a fairly wide problem.
>>
>> I would have to disagree. I spend a lot of time writing code that
>> generates SQL from a business app and feel strongly that any
>> optimisation is my responsibility.
>>
>
> The point to a BI tool like BO is to abstract the data collection
> and do
> it dynamically.  The SQL is built at run time because the tool is
> designed to give the end user as much flexibility as the data
> structure
> allows to query the data however they want.
>
> It isn't feasible, possible, or recommended to rewrite all of the
> possible generated SQL that could be designed at runtime by the tool.

No, but it is feasible to expect the tool to generate well-formed
queries without redundant clauses.  There are plenty that do.

Erik Jones

DBA | Emma®
erik@myemma.com
800.595.4401 or 615.292.5888
615.292.0777 (fax)

Emma helps organizations everywhere communicate & market in style.
Visit us online at http://www.myemma.com




Re: Optimizer : query rewrite and execution plan ?

From
"Roberts, Jon"
Date:
> >
> >>> Since the SQL is not your fault and difficult to control, it is an
> >>> argument in favour of an optional planner mode that would perform
> >>> additional checks for redundant clauses of various kinds. The
> > default
> >>> for that would be "off" since most people don't suffer from this
> >>> problem. BO isn't the only SQL generating-client out there, so I
> > think
> >>> this is a fairly wide problem.
> >>
> >> I would have to disagree. I spend a lot of time writing code that
> >> generates SQL from a business app and feel strongly that any
> >> optimisation is my responsibility.
> >>
> >
> > The point to a BI tool like BO is to abstract the data collection
> > and do
> > it dynamically.  The SQL is built at run time because the tool is
> > designed to give the end user as much flexibility as the data
> > structure
> > allows to query the data however they want.
> >
> > It isn't feasible, possible, or recommended to rewrite all of the
> > possible generated SQL that could be designed at runtime by the
tool.
>
> No, but it is feasible to expect the tool to generate well-formed
> queries without redundant clauses.  There are plenty that do.
>


Agreed.


Jon

Re: Optimizer : query rewrite and execution plan ?

From
Tom Lane
Date:
Theo Kramer <theo@flame.co.za> writes:
> On Wed, 2008-02-06 at 11:53 +0000, Simon Riggs wrote:
>> Since the SQL is not your fault and difficult to control, it is an
>> argument in favour of an optional planner mode that would perform
>> additional checks for redundant clauses of various kinds. The default
>> for that would be "off" since most people don't suffer from this
>> problem. BO isn't the only SQL generating-client out there, so I think
>> this is a fairly wide problem.

> I would have to disagree. I spend a lot of time writing code that
> generates SQL from a business app and feel strongly that any
> optimisation is my responsibility.

Disagree with what?  If that's your feeling then you'd leave the setting
"off", and no harm done.

We used to have code that removed duplicate WHERE clauses (check the
revision history for prepqual.c).  It was taken out because it consumed
excessive amounts of planning time without accomplishing a darn thing
for most queries.  There is no chance that it will be put back in as the
only behavior, or even the default behavior, but I can see the reasoning
for offering an option as Simon suggests.

            regards, tom lane

Re: Optimizer : query rewrite and execution plan ?

From
Simon Riggs
Date:
On Wed, 2008-02-06 at 11:00 -0500, Tom Lane wrote:
> Theo Kramer <theo@flame.co.za> writes:
> > On Wed, 2008-02-06 at 11:53 +0000, Simon Riggs wrote:
> >> Since the SQL is not your fault and difficult to control, it is an
> >> argument in favour of an optional planner mode that would perform
> >> additional checks for redundant clauses of various kinds. The default
> >> for that would be "off" since most people don't suffer from this
> >> problem. BO isn't the only SQL generating-client out there, so I think
> >> this is a fairly wide problem.

> We used to have code that removed duplicate WHERE clauses (check the
> revision history for prepqual.c).  It was taken out because it consumed
> excessive amounts of planning time without accomplishing a darn thing
> for most queries.  There is no chance that it will be put back in as the
> only behavior, or even the default behavior, but I can see the reasoning
> for offering an option as Simon suggests.

I was wondering if we might do that automatically? It seems easy to
imagine a switch, but I wonder if we'd be able to set it correctly in
enough situations to make it worthwhile.

Say if cost of best plan >= N then recheck query for strangeness. If
anything found, re-plan query.

That way we only pay the cost of checking for longer queries and we only
actually re-plan for queries that will benefit.

--
  Simon Riggs
  2ndQuadrant  http://www.2ndQuadrant.com


Re: Optimizer : query rewrite and execution plan ?

From
Tom Lane
Date:
Simon Riggs <simon@2ndquadrant.com> writes:
> Say if cost of best plan >= N then recheck query for strangeness. If
> anything found, re-plan query.

Whatever makes you think that would be useful?

The usual result of undetected duplicate WHERE clauses is an
*underestimate* of runtime, not an overestimate (because it thinks
too few tuples will be selected).

            regards, tom lane