mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
Simplify the planner's new representation of indexable clauses a little.
In commit 1a8d5afb0, I thought it'd be a good idea to define IndexClause.indexquals as NIL in the most common case where the given clause (IndexClause.rinfo) is usable exactly as-is. It'd be more consistent to define the indexquals in that case as being a one-element list containing IndexClause.rinfo, but I thought saving the palloc overhead for making such a list would be worthwhile. In hindsight, that was a great example of "premature optimization is the root of all evil": it's complicated everyplace that needs to deal with the indexquals, requiring duplicative code to handle both the simple case and the not-simple case. I'd initially found that tolerable but it's getting less so as I mop up some areas that I'd not touched in 1a8d5afb0. In any case, two more pallocs during a planner run are surely at the noise level (a conclusion confirmed by a bit of microbenchmarking). So let's change this decision before it becomes set in stone, and insist that IndexClause.indexquals always be a valid list of the actual index quals for the clause. Discussion: https://postgr.es/m/24586.1550106354@sss.pgh.pa.us
This commit is contained in:
parent
86eea78694
commit
8fd3fdd85a
@ -2435,7 +2435,7 @@ match_clause_to_indexcol(PlannerInfo *root,
|
|||||||
{
|
{
|
||||||
iclause = makeNode(IndexClause);
|
iclause = makeNode(IndexClause);
|
||||||
iclause->rinfo = rinfo;
|
iclause->rinfo = rinfo;
|
||||||
iclause->indexquals = NIL;
|
iclause->indexquals = list_make1(rinfo);
|
||||||
iclause->lossy = false;
|
iclause->lossy = false;
|
||||||
iclause->indexcol = indexcol;
|
iclause->indexcol = indexcol;
|
||||||
iclause->indexcols = NIL;
|
iclause->indexcols = NIL;
|
||||||
@ -2599,7 +2599,7 @@ match_opclause_to_indexcol(PlannerInfo *root,
|
|||||||
{
|
{
|
||||||
iclause = makeNode(IndexClause);
|
iclause = makeNode(IndexClause);
|
||||||
iclause->rinfo = rinfo;
|
iclause->rinfo = rinfo;
|
||||||
iclause->indexquals = NIL;
|
iclause->indexquals = list_make1(rinfo);
|
||||||
iclause->lossy = false;
|
iclause->lossy = false;
|
||||||
iclause->indexcol = indexcol;
|
iclause->indexcol = indexcol;
|
||||||
iclause->indexcols = NIL;
|
iclause->indexcols = NIL;
|
||||||
@ -2819,7 +2819,7 @@ match_saopclause_to_indexcol(RestrictInfo *rinfo,
|
|||||||
IndexClause *iclause = makeNode(IndexClause);
|
IndexClause *iclause = makeNode(IndexClause);
|
||||||
|
|
||||||
iclause->rinfo = rinfo;
|
iclause->rinfo = rinfo;
|
||||||
iclause->indexquals = NIL;
|
iclause->indexquals = list_make1(rinfo);
|
||||||
iclause->lossy = false;
|
iclause->lossy = false;
|
||||||
iclause->indexcol = indexcol;
|
iclause->indexcol = indexcol;
|
||||||
iclause->indexcols = NIL;
|
iclause->indexcols = NIL;
|
||||||
@ -3078,7 +3078,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
|||||||
* usable as index quals.
|
* usable as index quals.
|
||||||
*/
|
*/
|
||||||
if (var_on_left && !iclause->lossy)
|
if (var_on_left && !iclause->lossy)
|
||||||
iclause->indexquals = NIL;
|
iclause->indexquals = list_make1(rinfo);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -3075,11 +3075,8 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
|||||||
|
|
||||||
Assert(!rinfo->pseudoconstant);
|
Assert(!rinfo->pseudoconstant);
|
||||||
subquals = lappend(subquals, rinfo->clause);
|
subquals = lappend(subquals, rinfo->clause);
|
||||||
if (iclause->indexquals)
|
|
||||||
subindexquals = list_concat(subindexquals,
|
subindexquals = list_concat(subindexquals,
|
||||||
get_actual_clauses(iclause->indexquals));
|
get_actual_clauses(iclause->indexquals));
|
||||||
else
|
|
||||||
subindexquals = lappend(subindexquals, rinfo->clause);
|
|
||||||
if (rinfo->parent_ec)
|
if (rinfo->parent_ec)
|
||||||
subindexECs = lappend(subindexECs, rinfo->parent_ec);
|
subindexECs = lappend(subindexECs, rinfo->parent_ec);
|
||||||
}
|
}
|
||||||
@ -4491,20 +4488,6 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
|
|||||||
{
|
{
|
||||||
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
||||||
int indexcol = iclause->indexcol;
|
int indexcol = iclause->indexcol;
|
||||||
|
|
||||||
if (iclause->indexquals == NIL)
|
|
||||||
{
|
|
||||||
/* rinfo->clause is directly usable as an indexqual */
|
|
||||||
Node *clause = (Node *) iclause->rinfo->clause;
|
|
||||||
|
|
||||||
stripped_indexquals = lappend(stripped_indexquals, clause);
|
|
||||||
clause = fix_indexqual_clause(root, index, indexcol,
|
|
||||||
clause, iclause->indexcols);
|
|
||||||
fixed_indexquals = lappend(fixed_indexquals, clause);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Process the derived indexquals */
|
|
||||||
ListCell *lc2;
|
ListCell *lc2;
|
||||||
|
|
||||||
foreach(lc2, iclause->indexquals)
|
foreach(lc2, iclause->indexquals)
|
||||||
@ -4518,7 +4501,6 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
|
|||||||
fixed_indexquals = lappend(fixed_indexquals, clause);
|
fixed_indexquals = lappend(fixed_indexquals, clause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*stripped_indexquals_p = stripped_indexquals;
|
*stripped_indexquals_p = stripped_indexquals;
|
||||||
*fixed_indexquals_p = fixed_indexquals;
|
*fixed_indexquals_p = fixed_indexquals;
|
||||||
|
@ -197,8 +197,6 @@ static bool get_actual_variable_range(PlannerInfo *root,
|
|||||||
Oid sortop,
|
Oid sortop,
|
||||||
Datum *min, Datum *max);
|
Datum *min, Datum *max);
|
||||||
static RelOptInfo *find_join_input_rel(PlannerInfo *root, Relids relids);
|
static RelOptInfo *find_join_input_rel(PlannerInfo *root, Relids relids);
|
||||||
static IndexQualInfo *deconstruct_indexqual(RestrictInfo *rinfo,
|
|
||||||
IndexOptInfo *index, int indexcol);
|
|
||||||
static List *add_predicate_to_quals(IndexOptInfo *index, List *indexQuals);
|
static List *add_predicate_to_quals(IndexOptInfo *index, List *indexQuals);
|
||||||
|
|
||||||
|
|
||||||
@ -5263,16 +5261,13 @@ get_index_quals(List *indexclauses)
|
|||||||
foreach(lc, indexclauses)
|
foreach(lc, indexclauses)
|
||||||
{
|
{
|
||||||
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
||||||
|
ListCell *lc2;
|
||||||
|
|
||||||
if (iclause->indexquals == NIL)
|
foreach(lc2, iclause->indexquals)
|
||||||
{
|
{
|
||||||
/* rinfo->clause is directly usable as an indexqual */
|
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
||||||
result = lappend(result, iclause->rinfo);
|
|
||||||
}
|
result = lappend(result, rinfo);
|
||||||
else
|
|
||||||
{
|
|
||||||
/* report the derived indexquals */
|
|
||||||
result = list_concat(result, list_copy(iclause->indexquals));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -5282,47 +5277,20 @@ List *
|
|||||||
deconstruct_indexquals(IndexPath *path)
|
deconstruct_indexquals(IndexPath *path)
|
||||||
{
|
{
|
||||||
List *result = NIL;
|
List *result = NIL;
|
||||||
IndexOptInfo *index = path->indexinfo;
|
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
|
||||||
foreach(lc, path->indexclauses)
|
foreach(lc, path->indexclauses)
|
||||||
{
|
{
|
||||||
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
||||||
int indexcol = iclause->indexcol;
|
int indexcol = iclause->indexcol;
|
||||||
IndexQualInfo *qinfo;
|
|
||||||
|
|
||||||
if (iclause->indexquals == NIL)
|
|
||||||
{
|
|
||||||
/* rinfo->clause is directly usable as an indexqual */
|
|
||||||
qinfo = deconstruct_indexqual(iclause->rinfo, index, indexcol);
|
|
||||||
result = lappend(result, qinfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Process the derived indexquals */
|
|
||||||
ListCell *lc2;
|
ListCell *lc2;
|
||||||
|
|
||||||
foreach(lc2, iclause->indexquals)
|
foreach(lc2, iclause->indexquals)
|
||||||
{
|
{
|
||||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
||||||
|
Expr *clause = rinfo->clause;
|
||||||
qinfo = deconstruct_indexqual(rinfo, index, indexcol);
|
|
||||||
result = lappend(result, qinfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IndexQualInfo *
|
|
||||||
deconstruct_indexqual(RestrictInfo *rinfo, IndexOptInfo *index, int indexcol)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Expr *clause;
|
|
||||||
IndexQualInfo *qinfo;
|
IndexQualInfo *qinfo;
|
||||||
|
|
||||||
clause = rinfo->clause;
|
|
||||||
|
|
||||||
qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
|
qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
|
||||||
qinfo->rinfo = rinfo;
|
qinfo->rinfo = rinfo;
|
||||||
qinfo->indexcol = indexcol;
|
qinfo->indexcol = indexcol;
|
||||||
@ -5357,8 +5325,10 @@ deconstruct_indexqual(RestrictInfo *rinfo, IndexOptInfo *index, int indexcol)
|
|||||||
(int) nodeTag(clause));
|
(int) nodeTag(clause));
|
||||||
}
|
}
|
||||||
|
|
||||||
return qinfo;
|
result = lappend(result, qinfo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1185,26 +1185,20 @@ typedef struct IndexPath
|
|||||||
* conditions is done by a planner support function attached to the
|
* conditions is done by a planner support function attached to the
|
||||||
* indexclause's top-level function or operator.
|
* indexclause's top-level function or operator.
|
||||||
*
|
*
|
||||||
* If indexquals is NIL, it means that rinfo->clause is directly usable as
|
* indexquals is a list of RestrictInfos for the directly-usable index
|
||||||
* an indexqual. Otherwise indexquals contains one or more directly-usable
|
* conditions associated with this IndexClause. In the simplest case
|
||||||
* indexqual conditions extracted from the given clause. The 'lossy' flag
|
* it's a one-element list whose member is iclause->rinfo. Otherwise,
|
||||||
* indicates whether the indexquals are semantically equivalent to the
|
* it contains one or more directly-usable indexqual conditions extracted
|
||||||
* original clause, or form a weaker condition.
|
* from the given clause. The 'lossy' flag indicates whether the
|
||||||
*
|
* indexquals are semantically equivalent to the original clause, or
|
||||||
* Currently, entries in indexquals are RestrictInfos, but they could perhaps
|
* represent a weaker condition.
|
||||||
* be bare clauses instead; the only advantage of making them RestrictInfos
|
|
||||||
* is the possibility of caching cost and selectivity information across
|
|
||||||
* multiple uses, and it's not clear that that's really worth the price of
|
|
||||||
* constructing RestrictInfos for them. Note however that the extended-stats
|
|
||||||
* machinery won't do anything with non-RestrictInfo clauses, so that would
|
|
||||||
* have to be fixed.
|
|
||||||
*
|
*
|
||||||
* Normally, indexcol is the index of the single index column the clause
|
* Normally, indexcol is the index of the single index column the clause
|
||||||
* works on, and indexcols is NIL. But if the clause is a RowCompareExpr,
|
* works on, and indexcols is NIL. But if the clause is a RowCompareExpr,
|
||||||
* indexcol is the index of the leading column, and indexcols is a list of
|
* indexcol is the index of the leading column, and indexcols is a list of
|
||||||
* all the affected columns. (Note that indexcols matches up with the
|
* all the affected columns. (Note that indexcols matches up with the
|
||||||
* columns of the actual indexable RowCompareExpr, which might be in
|
* columns of the actual indexable RowCompareExpr in indexquals, which
|
||||||
* indexquals rather than rinfo.)
|
* might be different from the original in rinfo.)
|
||||||
*
|
*
|
||||||
* An IndexPath's IndexClause list is required to be ordered by index
|
* An IndexPath's IndexClause list is required to be ordered by index
|
||||||
* column, i.e. the indexcol values must form a nondecreasing sequence.
|
* column, i.e. the indexcol values must form a nondecreasing sequence.
|
||||||
@ -1214,7 +1208,7 @@ typedef struct IndexClause
|
|||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
struct RestrictInfo *rinfo; /* original restriction or join clause */
|
struct RestrictInfo *rinfo; /* original restriction or join clause */
|
||||||
List *indexquals; /* indexqual(s) derived from it, or NIL */
|
List *indexquals; /* indexqual(s) derived from it */
|
||||||
bool lossy; /* are indexquals a lossy version of clause? */
|
bool lossy; /* are indexquals a lossy version of clause? */
|
||||||
AttrNumber indexcol; /* index column the clause uses (zero-based) */
|
AttrNumber indexcol; /* index column the clause uses (zero-based) */
|
||||||
List *indexcols; /* multiple index columns, if RowCompare */
|
List *indexcols; /* multiple index columns, if RowCompare */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user