Re: Problems with plan estimates in postgres_fdw

Antonin Houska <ah@cybertec.at>

From: Antonin Houska <ah@cybertec.at>
To: Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp>
Cc: Tom Lane <tgl@sss.pgh.pa.us>, Andrew Gierth <andrew@tao11.riddles.org.uk>, pgsql-hackers@postgresql.org
Date: 2019-02-15T12:46:02Z
Lists: pgsql-hackers
Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp> wrote:

> (2019/02/12 18:03), Antonin Houska wrote:
> > Etsuro Fujita<fujita.etsuro@lab.ntt.co.jp>  wrote:
> >> (2019/02/08 2:04), Antonin Houska wrote:
> >>>
> >>> And maybe related problem: why should FDW care about the effect of
> >>> apply_scanjoin_target_to_paths() like you claim to do here?
> >>>
> >>> 	/*
> >>> 	 * If this is UPPERREL_ORDERED and/or UPPERREL_FINAL steps on the
> >>> 	 * final scan/join relation, the costs obtained from the cache
> >>> 	 * wouldn't yet contain the eval cost for the final scan/join target,
> >>> 	 * which would have been updated by apply_scanjoin_target_to_paths();
> >>> 	 * add the eval cost now.
> >>> 	 */
> >>> 	if (fpextra&&   !IS_UPPER_REL(foreignrel))
> >>> 	{
> >>> 		/* The costs should have been obtained from the cache. */
> >>> 		Assert(fpinfo->rel_startup_cost>= 0&&
> >>> 			fpinfo->rel_total_cost>= 0);
> >>>
> >>> 		startup_cost += foreignrel->reltarget->cost.startup;
> >>> 		run_cost += foreignrel->reltarget->cost.per_tuple * rows;
> >>> 	}
> >>>
> >>> I think it should not, whether "foreignrel" means "input_rel" or "output_rel"
> >>> from the perspective of postgresGetForeignUpperPaths().
> >>
> >> I added this before costing the sort operation below, because 1) the cost of
> >> evaluating the scan/join target might not be zero (consider the case where
> >> sort columns are not simple Vars, for example) and 2) the cost of sorting
> >> takes into account the underlying path's startup/total costs.  Maybe I'm
> >> missing something, though.
> >
> > My understanding is that the "input_rel" argument of
> > postgresGetForeignUpperPaths() should already have been processed by
> > postgresGetForeignPaths() or postgresGetForeignJoinPaths() (or actually by
> > postgresGetForeignUpperPaths() called with different "stage" too). Therefore
> > it should already have the "fdw_private" field initialized. The estimates in
> > the corresponding PgFdwRelationInfo should already include the reltarget
> > costs, as set previously by estimate_path_cost_size().
> 
> Right, but what I'm saying here is: the costs of evaluating the final
> scan/join target updated by apply_scanjoin_target_to_paths() wouldn't be yet
> included in the costs we calculated using local statistics when called from
> postgresGetForeignPaths() or postgresGetForeignJoinPaths(). Let me explain
> using an example:
> 
>     SELECT a+b FROM foreign_table LIMIT 10;
> 
> For this query, the reltarget for the foreign_table would be {a, b} when
> called from postgresGetForeignPaths() (see build_base_rel_tlists()). The costs
> of evaluating simple Vars are zeroes, so we wouldn't charge any costs for
> tlist evaluation when estimating the costs of a basic foreign table scan in
> that callback routine, but the final scan target, with which the reltarget
> will be replaced later by apply_scanjoin_target_to_paths(), would be {a+b}, so
> we need to adjust the costs of the basic foreign table scan, cached in the
> PgFdwRelationInfo for the input_rel (ie, the foreign_table), so that eval
> costs for the replaced tlist are included when called from
> postgresGetForeignUpperPaths() with the UPPERREL_FINAL stage, as the costs of
> evaluating the expression 'a+b' wouldn't be zeroes.

ok, I understand now. I assume that the patch

https://www.postgresql.org/message-id/5C66A056.60007%40lab.ntt.co.jp

obsoletes the code snippet we discussed above.

-- 
Antonin Houska
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26, A-2700 Wiener Neustadt
Web: https://www.cybertec-postgresql.com


Commits

  1. postgres_fdw: Perform the (FINAL, NULL) upperrel operations remotely.

  2. Refactor create_limit_path() to share cost adjustment code with FDWs.

  3. postgres_fdw: Modify regression tests for EPQ-related planning problems.

  4. postgres_fdw: Perform the (ORDERED, NULL) upperrel operations remotely.

  5. Save PathTargets for distinct/ordered relations in root->upper_targets[].

  6. Split create_foreignscan_path() into three functions.

  7. Fix test case for 'outer pathkeys do not match mergeclauses' fix.

  8. postgres_fdw: Avoid 'outer pathkeys do not match mergeclauses' error.