Skip to content

Commit 6161766

Browse files
committed
Adjust remove_redundant_join_clauses() so that when it has a choice
of which redundant clause to remove, it removes the more expensive one. In simple scenarios the clauses will be like 'var = var' and there's no difference, but we are now capable of considering cases where there are sub-selects in the clauses, and it makes a BIG difference.
1 parent df79b84 commit 6161766

File tree

1 file changed

+60
-29
lines changed

1 file changed

+60
-29
lines changed

src/backend/optimizer/util/restrictinfo.c

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.25 2004/01/05 23:39:54 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.26 2004/02/27 21:48:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include "postgres.h"
1616

1717
#include "optimizer/clauses.h"
18+
#include "optimizer/cost.h"
1819
#include "optimizer/paths.h"
1920
#include "optimizer/restrictinfo.h"
2021
#include "optimizer/var.h"
@@ -27,7 +28,7 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause,
2728
static Expr *make_sub_restrictinfos(Expr *clause,
2829
bool is_pushed_down,
2930
bool valid_everywhere);
30-
static bool join_clause_is_redundant(Query *root,
31+
static RestrictInfo *join_clause_is_redundant(Query *root,
3132
RestrictInfo *rinfo,
3233
List *reference_list,
3334
JoinType jointype);
@@ -317,17 +318,42 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list,
317318
{
318319
List *result = NIL;
319320
List *item;
321+
QualCost cost;
322+
323+
/*
324+
* If there are any redundant clauses, we want to eliminate the ones
325+
* that are more expensive in favor of the ones that are less so.
326+
* Run cost_qual_eval() to ensure the eval_cost fields are set up.
327+
*/
328+
cost_qual_eval(&cost, restrictinfo_list);
329+
330+
/*
331+
* We don't have enough knowledge yet to be able to estimate the number
332+
* of times a clause might be evaluated, so it's hard to weight the
333+
* startup and per-tuple costs appropriately. For now just weight 'em
334+
* the same.
335+
*/
336+
#define CLAUSECOST(r) ((r)->eval_cost.startup + (r)->eval_cost.per_tuple)
320337

321338
foreach(item, restrictinfo_list)
322339
{
323340
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
341+
RestrictInfo *prevrinfo;
324342

325-
/* drop it if redundant with any prior clause */
326-
if (join_clause_is_redundant(root, rinfo, result, jointype))
327-
continue;
328-
329-
/* otherwise, add it to result list */
330-
result = lappend(result, rinfo);
343+
/* is it redundant with any prior clause? */
344+
prevrinfo = join_clause_is_redundant(root, rinfo, result, jointype);
345+
if (prevrinfo == NULL)
346+
{
347+
/* no, so add it to result list */
348+
result = lappend(result, rinfo);
349+
}
350+
else if (CLAUSECOST(rinfo) < CLAUSECOST(prevrinfo))
351+
{
352+
/* keep this one, drop the previous one */
353+
result = lremove(prevrinfo, result);
354+
result = lappend(result, rinfo);
355+
}
356+
/* else, drop this one */
331357
}
332358

333359
return result;
@@ -361,7 +387,7 @@ select_nonredundant_join_clauses(Query *root,
361387
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
362388

363389
/* drop it if redundant with any reference clause */
364-
if (join_clause_is_redundant(root, rinfo, reference_list, jointype))
390+
if (join_clause_is_redundant(root, rinfo, reference_list, jointype) != NULL)
365391
continue;
366392

367393
/* otherwise, add it to result list */
@@ -373,7 +399,8 @@ select_nonredundant_join_clauses(Query *root,
373399

374400
/*
375401
* join_clause_is_redundant
376-
* Returns true if rinfo is redundant with any clause in reference_list.
402+
* If rinfo is redundant with any clause in reference_list,
403+
* return one such clause; otherwise return NULL.
377404
*
378405
* This is the guts of both remove_redundant_join_clauses and
379406
* select_nonredundant_join_clauses. See the docs above for motivation.
@@ -398,49 +425,53 @@ select_nonredundant_join_clauses(Query *root,
398425
* then they're not really redundant, because one constrains the
399426
* joined rows after addition of null fill rows, and the other doesn't.
400427
*/
401-
static bool
428+
static RestrictInfo *
402429
join_clause_is_redundant(Query *root,
403430
RestrictInfo *rinfo,
404431
List *reference_list,
405432
JoinType jointype)
406433
{
434+
List *refitem;
435+
407436
/* always consider exact duplicates redundant */
408-
/* XXX would it be sufficient to use ptrMember here? */
409-
if (member(rinfo, reference_list))
410-
return true;
437+
foreach(refitem, reference_list)
438+
{
439+
RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
440+
441+
if (equal(rinfo, refrinfo))
442+
return refrinfo;
443+
}
411444

412445
/* check for redundant merge clauses */
413446
if (rinfo->mergejoinoperator != InvalidOid)
414447
{
415-
bool redundant = false;
416-
List *refitem;
417-
418448
/* do the cheap test first: is it a "var = const" clause? */
419449
if (bms_is_empty(rinfo->left_relids) ||
420450
bms_is_empty(rinfo->right_relids))
421-
return false; /* var = const, so not redundant */
451+
return NULL; /* var = const, so not redundant */
422452

423453
cache_mergeclause_pathkeys(root, rinfo);
424454

425455
foreach(refitem, reference_list)
426456
{
427457
RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
428458

429-
if (refrinfo->mergejoinoperator != InvalidOid &&
430-
rinfo->left_pathkey == refrinfo->left_pathkey &&
431-
rinfo->right_pathkey == refrinfo->right_pathkey &&
432-
(rinfo->is_pushed_down == refrinfo->is_pushed_down ||
433-
!IS_OUTER_JOIN(jointype)))
459+
if (refrinfo->mergejoinoperator != InvalidOid)
434460
{
435-
redundant = true;
436-
break;
461+
cache_mergeclause_pathkeys(root, refrinfo);
462+
463+
if (rinfo->left_pathkey == refrinfo->left_pathkey &&
464+
rinfo->right_pathkey == refrinfo->right_pathkey &&
465+
(rinfo->is_pushed_down == refrinfo->is_pushed_down ||
466+
!IS_OUTER_JOIN(jointype)))
467+
{
468+
/* Yup, it's redundant */
469+
return refrinfo;
470+
}
437471
}
438472
}
439-
440-
if (redundant)
441-
return true; /* var = var, so redundant */
442473
}
443474

444475
/* otherwise, not redundant */
445-
return false;
476+
return NULL;
446477
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy