Thanks a lot for your detailed explanation. I will try ASAP with no
DISTINCT ( we are quite sure it is not needed anyway ), and report back
here.

Michaƫl

2017-08-21 23:52 GMT+02:00 David Rowley <david.row...@2ndquadrant.com>:

> On 19 August 2017 at 04:46, kimaidou <kimai...@gmail.com> wrote:
> > When we call the WHERE on the view:
> >
> > EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS)
> > SELECT *
> > FROM "qgep"."vw_qgep_reach"
> > WHERE "progression_geometry" &&
> > st_makeenvelope(1728327.03249295568093657,8240789.
> 26074041239917278,1728608.10987572139129043,8240958.
> 16933418624103069,3949)
> >
> >
> > The query plan is "wrong", as PostgreSQL seems to consider it should do a
> > seq scan on the tables, and only afterwards filter with the WHERE:
> > https://explain.depesz.com/s/wXV
> >
> > The query takes about 1 second instead of less than 100ms.
> >
> > Do you have any hint on this kind of issue ?
>
> This is by design due to the DISTINCT ON() clause. Only quals which
> filter columns which are in the DISTINCT ON can be safely pushed down.
>
> Consider the following, where I've manually pushed the WHERE clause.
>
> postgres=# create table tt (a int, b int);
> CREATE TABLE
> postgres=# create index on tt (a);
> CREATE INDEX
> postgres=# insert into tt values(1,1),(1,2),(2,1),(2,2);
> INSERT 0 4
> postgres=# select * from (select distinct on (a) a,b from tt order by
> a,b) tt where b = 2;
>  a | b
> ---+---
> (0 rows)
>
>
> postgres=# select * from (select distinct on (a) a,b from tt where b =
> 2 order by a,b) tt;
>  a | b
> ---+---
>  1 | 2
>  2 | 2
> (2 rows)
>
> Note the results are not the same.
>
> If I'd done WHERE a = 2, then the planner would have pushed the qual
> down into the subquery.
>
> More reading in check_output_expressions() in allpaths.c:
>
> /* If subquery uses DISTINCT ON, check point 3 */
> if (subquery->hasDistinctOn &&
> !targetIsInSortList(tle, InvalidOid, subquery->distinctClause))
> {
> /* non-DISTINCT column, so mark it unsafe */
> safetyInfo->unsafeColumns[tle->resno] = true;
> continue;
> }
>
> The comment for point 3 reads:
>
>  * 3. If the subquery uses DISTINCT ON, we must not push down any quals
> that
>  * refer to non-DISTINCT output columns, because that could change the set
>  * of rows returned.  (This condition is vacuous for DISTINCT, because then
>  * there are no non-DISTINCT output columns, so we needn't check.  Note
> that
>  * subquery_is_pushdown_safe already reported that we can't use volatile
>  * quals if there's DISTINCT or DISTINCT ON.)
>
>
> --
>  David Rowley                   http://www.2ndQuadrant.com/
>  PostgreSQL Development, 24x7 Support, Training & Services
>

Reply via email to