mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Improve UniquePath logic to detect the case where the input is already
known unique (eg, it is a SELECT DISTINCT ... subquery), and not do a redundant unique-ification step.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.97 2004/01/05 05:07:35 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.98 2004/01/05 18:04:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,12 +20,14 @@
|
||||
#include "executor/executor.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/plannodes.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/cost.h"
|
||||
#include "optimizer/pathnode.h"
|
||||
#include "optimizer/paths.h"
|
||||
#include "optimizer/restrictinfo.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/selfuncs.h"
|
||||
#include "utils/syscache.h"
|
||||
@ -546,6 +548,30 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
|
||||
|
||||
pathnode->subpath = subpath;
|
||||
|
||||
/*
|
||||
* If the input is a subquery that uses DISTINCT, we don't need to do
|
||||
* anything; its output is already unique. (Are there any other cases
|
||||
* in which we can easily prove the input must be distinct?)
|
||||
*/
|
||||
if (rel->rtekind == RTE_SUBQUERY)
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(rel->relid, root->rtable);
|
||||
Query *subquery = rte->subquery;
|
||||
|
||||
if (has_distinct_clause(subquery))
|
||||
{
|
||||
pathnode->umethod = UNIQUE_PATH_NOOP;
|
||||
pathnode->rows = rel->rows;
|
||||
pathnode->path.startup_cost = subpath->startup_cost;
|
||||
pathnode->path.total_cost = subpath->total_cost;
|
||||
pathnode->path.pathkeys = subpath->pathkeys;
|
||||
|
||||
rel->cheapest_unique_path = (Path *) pathnode;
|
||||
|
||||
return pathnode;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to identify the targetlist that will actually be unique-ified.
|
||||
* In current usage, this routine is only used for sub-selects of IN
|
||||
@ -599,7 +625,7 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
|
||||
* compare costs. We only try this if we know the targetlist for sure
|
||||
* (else we can't be sure about the datatypes involved).
|
||||
*/
|
||||
pathnode->use_hash = false;
|
||||
pathnode->umethod = UNIQUE_PATH_SORT;
|
||||
if (enable_hashagg && sub_targetlist && hash_safe_tlist(sub_targetlist))
|
||||
{
|
||||
/*
|
||||
@ -617,11 +643,11 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
|
||||
subpath->total_cost,
|
||||
rel->rows);
|
||||
if (agg_path.total_cost < sort_path.total_cost)
|
||||
pathnode->use_hash = true;
|
||||
pathnode->umethod = UNIQUE_PATH_HASH;
|
||||
}
|
||||
}
|
||||
|
||||
if (pathnode->use_hash)
|
||||
if (pathnode->umethod == UNIQUE_PATH_HASH)
|
||||
{
|
||||
pathnode->path.startup_cost = agg_path.startup_cost;
|
||||
pathnode->path.total_cost = agg_path.total_cost;
|
||||
|
Reference in New Issue
Block a user