1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Extend code that deduces implied equality clauses to detect whether a

clause being added to a particular restriction-clause list is redundant
with those already in the list.  This avoids useless work at runtime,
and (perhaps more importantly) keeps the selectivity estimation routines
from generating too-small estimates of numbers of output rows.
Also some minor improvements in OPTIMIZER_DEBUG displays.
This commit is contained in:
Tom Lane
2001-10-18 16:11:42 +00:00
parent 5045004958
commit 6254465d06
9 changed files with 373 additions and 110 deletions

View File

@ -8,13 +8,16 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.78 2001/07/31 17:56:30 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.79 2001/10/18 16:11:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#ifdef OPTIMIZER_DEBUG
#include "nodes/print.h"
#endif
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
@ -42,11 +45,6 @@ static void set_subquery_pathlist(Query *root, RelOptInfo *rel,
static RelOptInfo *make_one_rel_by_joins(Query *root, int levels_needed,
List *initial_rels);
#ifdef OPTIMIZER_DEBUG
static void debug_print_rel(Query *root, RelOptInfo *rel);
#endif
/*
* make_one_rel
@ -116,6 +114,10 @@ set_base_rel_pathlists(Query *root)
/* Plain relation */
set_plain_rel_pathlist(root, rel, rte);
}
#ifdef OPTIMIZER_DEBUG
debug_print_rel(root, rel);
#endif
}
}
@ -520,10 +522,22 @@ make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels)
#ifdef OPTIMIZER_DEBUG
static void
print_joinclauses(Query *root, List *clauses)
print_relids(Relids relids)
{
List *l;
foreach(l, relids)
{
printf("%d", lfirsti(l));
if (lnext(l))
printf(" ");
}
}
static void
print_restrictclauses(Query *root, List *clauses)
{
List *l;
extern void print_expr(Node *expr, List *rtable); /* in print.c */
foreach(l, clauses)
{
@ -531,21 +545,17 @@ print_joinclauses(Query *root, List *clauses)
print_expr((Node *) c->clause, root->rtable);
if (lnext(l))
printf(" ");
printf(", ");
}
}
static void
print_path(Query *root, Path *path, int indent)
{
char *ptype = NULL;
JoinPath *jp;
bool join = false;
const char *ptype;
bool join;
int i;
for (i = 0; i < indent; i++)
printf("\t");
switch (nodeTag(path))
{
case T_Path:
@ -556,6 +566,10 @@ print_path(Query *root, Path *path, int indent)
ptype = "IdxScan";
join = false;
break;
case T_TidPath:
ptype = "TidScan";
join = false;
break;
case T_NestPath:
ptype = "Nestloop";
join = true;
@ -569,82 +583,82 @@ print_path(Query *root, Path *path, int indent)
join = true;
break;
default:
ptype = "???Path";
join = false;
break;
}
for (i = 0; i < indent; i++)
printf("\t");
printf("%s(", ptype);
print_relids(path->parent->relids);
printf(") rows=%.0f cost=%.2f..%.2f\n",
path->parent->rows, path->startup_cost, path->total_cost);
if (path->pathkeys)
{
for (i = 0; i < indent; i++)
printf("\t");
printf(" pathkeys: ");
print_pathkeys(path->pathkeys, root->rtable);
}
if (join)
{
jp = (JoinPath *) path;
JoinPath *jp = (JoinPath *) path;
printf("%s rows=%.0f cost=%.2f..%.2f\n",
ptype, path->parent->rows,
path->startup_cost, path->total_cost);
for (i = 0; i < indent; i++)
printf("\t");
printf(" clauses: ");
print_restrictclauses(root, jp->joinrestrictinfo);
printf("\n");
if (path->pathkeys)
if (nodeTag(path) == T_MergePath)
{
for (i = 0; i < indent; i++)
printf("\t");
printf(" pathkeys=");
print_pathkeys(path->pathkeys, root->rtable);
}
MergePath *mp = (MergePath *) path;
switch (nodeTag(path))
{
case T_MergePath:
case T_HashPath:
if (mp->outersortkeys || mp->innersortkeys)
{
for (i = 0; i < indent; i++)
printf("\t");
printf(" clauses=(");
print_joinclauses(root, jp->joinrestrictinfo);
printf(")\n");
if (nodeTag(path) == T_MergePath)
{
MergePath *mp = (MergePath *) path;
if (mp->outersortkeys || mp->innersortkeys)
{
for (i = 0; i < indent; i++)
printf("\t");
printf(" sortouter=%d sortinner=%d\n",
((mp->outersortkeys) ? 1 : 0),
((mp->innersortkeys) ? 1 : 0));
}
}
break;
default:
break;
printf(" sortouter=%d sortinner=%d\n",
((mp->outersortkeys) ? 1 : 0),
((mp->innersortkeys) ? 1 : 0));
}
}
print_path(root, jp->outerjoinpath, indent + 1);
print_path(root, jp->innerjoinpath, indent + 1);
}
else
{
int relid = lfirsti(path->parent->relids);
printf("%s(%d) rows=%.0f cost=%.2f..%.2f\n",
ptype, relid, path->parent->rows,
path->startup_cost, path->total_cost);
if (path->pathkeys)
{
for (i = 0; i < indent; i++)
printf("\t");
printf(" pathkeys=");
print_pathkeys(path->pathkeys, root->rtable);
}
}
}
static void
void
debug_print_rel(Query *root, RelOptInfo *rel)
{
List *l;
printf("(");
foreach(l, rel->relids)
printf("%d ", lfirsti(l));
printf("RELOPTINFO (");
print_relids(rel->relids);
printf("): rows=%.0f width=%d\n", rel->rows, rel->width);
if (rel->baserestrictinfo)
{
printf("\tbaserestrictinfo: ");
print_restrictclauses(root, rel->baserestrictinfo);
printf("\n");
}
foreach(l, rel->joininfo)
{
JoinInfo *j = (JoinInfo *) lfirst(l);
printf("\tjoininfo (");
print_relids(j->unjoined_relids);
printf("): ");
print_restrictclauses(root, j->jinfo_restrictinfo);
printf("\n");
}
printf("\tpath list:\n");
foreach(l, rel->pathlist)
print_path(root, lfirst(l), 1);
@ -652,6 +666,8 @@ debug_print_rel(Query *root, RelOptInfo *rel)
print_path(root, rel->cheapest_startup_path, 1);
printf("\n\tcheapest total path:\n");
print_path(root, rel->cheapest_total_path, 1);
printf("\n");
fflush(stdout);
}
#endif /* OPTIMIZER_DEBUG */