Re: Planner features, discussion

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: David Fetter <david(at)fetter(dot)org>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Planner features, discussion
Date: 2010-07-15 01:05:23
Message-ID: 4C3E5ED3.2060509@postnewspapers.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On 15/07/10 00:34, David Fetter wrote:

>> => WITH aconstant(constval) AS (VALUES(1)) SELECT x.*, constval FROM
>> generate_series(1,10) AS x;
>> ERROR: column "constval" does not exist
>> LINE 1: ...TH aconstant(constval) AS (VALUES(1)) SELECT x.*, constval F...
>
> You missed the CROSS JOIN, which you could make implicit, even though
> implicit CROSS JOINs are bad coding style:

It was an example of how it'd be nice to avoid the need for a join when
dealing with scalar values. I'd love to be able to write:

WITH aconstant AS (1)
SELECT x.*, aconstant FROM generate_series(1,10) AS x;

... but can't presently do so because the WITH terms are only visible as
potential from-list items.

> WITH aconstant(constval) AS (VALUES(1))
> SELECT x.*, constval
> FROM
> generate_series(1,10) AS x
> CROSS JOIN
> aconstant;
> x | constval
> ----+----------
> 1 | 1
> 2 | 1
> 3 | 1
> 4 | 1
> 5 | 1
> 6 | 1
> 7 | 1
> 8 | 1
> 9 | 1
> 10 | 1
> (10 rows)

Using a cross join can often result in an undersired and expensive
nested loop, (I think) materialize, etc. In this case, the planner is
using a nested loop to join `aconstant' with the output of the function
scan:

> Nested Loop (cost=0.01..22.53 rows=1000 width=8) (actual time=0.049..0.133 rows=10 loops=1)
> CTE aconstant
> -> Values Scan on "*VALUES*" (cost=0.00..0.01 rows=1 width=4) (actual time=0.004..0.006 rows=1 loops=1)
> -> CTE Scan on aconstant (cost=0.00..0.02 rows=1 width=4) (actual time=0.015..0.023 rows=1 loops=1)
> -> Function Scan on generate_series x (cost=0.00..12.50 rows=1000 width=4) (actual time=0.022..0.045 rows=10 loops=1)
> Total runtime: 0.223 ms

as compared to what happens when I explicitly insert the constant by
hand or wrap the query up in an SQL function that takes the constant as
a parameter:

> Function Scan on generate_series x (cost=0.00..12.50 rows=1000 width=4) (actual time=0.027..0.054 rows=10 loops=1)
> Total runtime: 0.125 ms

In this trivial dummy example, it doesn't matter much. But in the kinds
of complex queries you often want to use a WITH expression for, it's not
appealing. If you're trying to use a WITH expression to avoid multiple
evaluation of an expensive function, the gains are often consumed in the
join costs.

So I land up relying on wrapping things up in SQL functions instead,
which is less than thrilling.

>> ... so you're forced to fall back on adding it as an additional join
>> expression - which isn't always reasonable or possible.
>
> Why not?

As above for one reason.

--
Craig Ringer

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Kenichiro Tanaka 2010-07-15 01:13:43 Re: about scape characters
Previous Message Richard Yen 2010-07-15 00:21:18 Re: coalesce seems to give strange results