Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit04578a9

Browse files
committed
Further cleanups of indexqual processing: simplify control
logic in indxpath.c, avoid generation of redundant indexscan paths for thesame relation and index.
1 parent037cac7 commit04578a9

File tree

3 files changed

+125
-157
lines changed

3 files changed

+125
-157
lines changed

‎src/backend/optimizer/path/indxpath.c

Lines changed: 114 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.66 1999/07/27 03:51:01 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.67 1999/07/30 04:07:23 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -67,8 +67,7 @@ static void indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
6767
List**clausegroups,List**outerrelids);
6868
staticList*index_innerjoin(Query*root,RelOptInfo*rel,RelOptInfo*index,
6969
List*clausegroup_list,List*outerrelids_list);
70-
staticList*create_index_path_group(Query*root,RelOptInfo*rel,RelOptInfo*index,
71-
List*clausegroup_list,booljoin);
70+
staticbooluseful_for_mergejoin(RelOptInfo*index,List*clausegroup_list);
7271
staticboolmatch_index_to_operand(intindexkey,Expr*operand,
7372
RelOptInfo*rel,RelOptInfo*index);
7473
staticboolfunction_index_operand(Expr*funcOpnd,RelOptInfo*rel,RelOptInfo*index);
@@ -84,19 +83,40 @@ static List *prefix_quals(Var *leftop, Oid expr_op,
8483
* create_index_paths()
8584
* Generate all interesting index paths for the given relation.
8685
*
87-
* To be considered for an index scan, an index must match one or more
88-
* restriction clauses or join clauses from the query's qual condition.
86+
* To be considered for an index scan, an index must match one or more
87+
* restriction clauses or join clauses from the query's qual condition.
8988
*
90-
* Note: an index scan might also be used simply to order the result,
91-
* either for use in a mergejoin or to satisfy an ORDER BY request.
92-
* That possibility is handled elsewhere.
89+
* There are two basic kinds of index scans. A "plain" index scan uses
90+
* only restriction clauses (possibly none at all) in its indexqual,
91+
* so it can be applied in any context. An "innerjoin" index scan uses
92+
* join clauses (plus restriction clauses, if available) in its indexqual.
93+
* Therefore it can only be used as the inner relation of a nestloop
94+
* join against an outer rel that includes all the other rels mentioned
95+
* in its join clauses. In that context, values for the other rels'
96+
* attributes are available and fixed during any one scan of the indexpath.
97+
*
98+
* This routine's return value is a list of plain IndexPaths for each
99+
* index the routine deems potentially interesting for the current query
100+
* (at most one IndexPath per index on the given relation). An innerjoin
101+
* path is also generated for each interesting combination of outer join
102+
* relations. The innerjoin paths are *not* in the return list, but are
103+
* appended to the "innerjoin" list of the relation itself.
104+
*
105+
* XXX An index scan might also be used simply to order the result. We
106+
* probably should create an index path for any index that matches the
107+
* query's ORDER BY condition, even if it doesn't seem useful for join
108+
* or restriction clauses. But currently, such a path would never
109+
* survive the path selection process, so there's no point. The selection
110+
* process needs to award bonus scores to indexscans that produce a
111+
* suitably-ordered result...
93112
*
94113
* 'rel' is the relation for which we want to generate index paths
95114
* 'indices' is a list of available indexes for 'rel'
96115
* 'restrictinfo_list' is a list of restrictinfo nodes for 'rel'
97116
* 'joininfo_list' is a list of joininfo nodes for 'rel'
98117
*
99-
* Returns a list of IndexPath access path descriptors.
118+
* Returns a list of IndexPath access path descriptors. Additional
119+
* IndexPath nodes may also be added to the rel->innerjoin list.
100120
*/
101121
List*
102122
create_index_paths(Query*root,
@@ -111,7 +131,7 @@ create_index_paths(Query *root,
111131
foreach(ilist,indices)
112132
{
113133
RelOptInfo*index= (RelOptInfo*)lfirst(ilist);
114-
List*scanclausegroups;
134+
List*restrictclauses;
115135
List*joinclausegroups;
116136
List*joinouterrelids;
117137

@@ -140,9 +160,8 @@ create_index_paths(Query *root,
140160
* of the index), but our poor brains are hurting already...
141161
*
142162
* We don't even think about special handling of 'or' clauses that
143-
* involve more than one relation, since they can't be processed by
144-
* a single indexscan path anyway. Currently, cnfify() is certain
145-
* to have restructured any such toplevel 'or' clauses anyway.
163+
* involve more than one relation (ie, are join clauses).
164+
* Can we do anything useful with those?
146165
*/
147166
match_index_orclauses(rel,
148167
index,
@@ -155,26 +174,33 @@ create_index_paths(Query *root,
155174
* restriction clauses, then create a path using those clauses
156175
* as indexquals.
157176
*/
158-
scanclausegroups=group_clauses_by_indexkey(rel,
159-
index,
160-
index->indexkeys,
161-
index->classlist,
162-
restrictinfo_list);
163-
164-
if (scanclausegroups!=NIL)
165-
retval=nconc(retval,
166-
create_index_path_group(root,
167-
rel,
168-
index,
169-
scanclausegroups,
170-
false));
177+
restrictclauses=group_clauses_by_indexkey(rel,
178+
index,
179+
index->indexkeys,
180+
index->classlist,
181+
restrictinfo_list);
182+
183+
if (restrictclauses!=NIL)
184+
retval=lappend(retval,
185+
create_index_path(root,rel,index,
186+
restrictclauses));
171187

172188
/*
173189
* 3. If this index can be used with any join clause, then create
174-
* pathnodes for each group of usable clauses.An index can be
175-
* used with a join clause if its ordering is useful for a
176-
* mergejoin, or if the index can possibly be used for scanning
177-
* the inner relation of a nestloop join.
190+
* an index path for it even if there were no restriction clauses.
191+
* (If there were, there is no need to make another index path.)
192+
* This will allow the index to be considered as a base for a
193+
* mergejoin in later processing.
194+
* Also, create an innerjoin index path for each combination of
195+
* other rels used in available join clauses. These paths will
196+
* be considered as the inner side of nestloop joins against
197+
* those sets of other rels.
198+
* indexable_joinclauses() finds clauses that are potentially
199+
* applicable to either case. useful_for_mergejoin() tests to
200+
* see whether any of the join clauses might support a mergejoin.
201+
* index_innerjoin() builds an innerjoin index path for each
202+
* potential set of outer rels, which we add to the rel's
203+
* innerjoin list.
178204
*/
179205
indexable_joinclauses(rel,index,
180206
joininfo_list,restrictinfo_list,
@@ -183,12 +209,13 @@ create_index_paths(Query *root,
183209

184210
if (joinclausegroups!=NIL)
185211
{
186-
retval=nconc(retval,
187-
create_index_path_group(root,
188-
rel,
189-
index,
190-
joinclausegroups,
191-
true));
212+
/* no need to create a plain path if we already did */
213+
if (restrictclauses==NIL&&
214+
useful_for_mergejoin(index,joinclausegroups))
215+
retval=lappend(retval,
216+
create_index_path(root,rel,index,
217+
NIL));
218+
192219
rel->innerjoin=nconc(rel->innerjoin,
193220
index_innerjoin(root,rel,index,
194221
joinclausegroups,
@@ -344,21 +371,18 @@ match_index_orclause(RelOptInfo *rel,
344371
* 'classes' are the classes of the index operators on those keys.
345372
* 'restrictinfo_list' is the list of available restriction clauses for 'rel'.
346373
*
347-
* Returns NIL if no clauses can be used with this index.
348-
* Otherwise, a list containing a single sublist is returned (indicating
349-
* to create_index_path_group() that a single IndexPath should be created).
350-
* The sublist contains the RestrictInfo nodes for all clauses that can be
374+
* Returns a list of all the RestrictInfo nodes for clauses that can be
351375
* used with this index.
352376
*
353-
* Thesublist is ordered by index key (but as far as I can tell, this is
377+
* Thelist is ordered by index key (but as far as I can tell, this is
354378
* an implementation artifact of this routine, and is not depended on by
355379
* any user of the returned list --- tgl 7/99).
356380
*
357381
* Note that in a multi-key index, we stop if we find a key that cannot be
358382
* used with any clause. For example, given an index on (A,B,C), we might
359-
* return ((C1 C2 C3 C4)) if we find that clauses C1 and C2 use column A,
360-
* clauses C3 and C4 use column B, and no clauses use column C. But if no
361-
* clauses match B we will return ((C1 C2)), whether or not there are
383+
* return (C1 C2 C3 C4) if we find that clauses C1 and C2 use column A,
384+
* clauses C3 and C4 use column B, and no clauses use column C. But if
385+
*noclauses match B we will return (C1 C2), whether or not there are
362386
* clauses matching column C, because the executor couldn't use them anyway.
363387
*/
364388
staticList*
@@ -407,9 +431,7 @@ group_clauses_by_indexkey(RelOptInfo *rel,
407431
}while (!DoneMatchingIndexKeys(indexkeys,index));
408432

409433
/* clausegroup_list holds all matched clauses ordered by indexkeys */
410-
if (clausegroup_list!=NIL)
411-
returnlcons(clausegroup_list,NIL);
412-
returnNIL;
434+
returnclausegroup_list;
413435
}
414436

415437
/*
@@ -418,9 +440,9 @@ group_clauses_by_indexkey(RelOptInfo *rel,
418440
*
419441
* This is much like group_clauses_by_indexkey(), but we consider both
420442
* join and restriction clauses. For each indexkey in the index, we
421-
* accept both join and restriction clauses that match it (since both
443+
* accept both join and restriction clauses that match it,since both
422444
* will make useful indexquals if the index is being used to scan the
423-
* inner side of a join). But there must be at least one matching
445+
* inner side of anestloopjoin. But there must be at least one matching
424446
* join clause, or we return NIL indicating that this index isn't useful
425447
* for joining.
426448
*/
@@ -486,22 +508,18 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
486508

487509
}while (!DoneMatchingIndexKeys(indexkeys,index));
488510

489-
/* clausegroup_list holds all matched clauses ordered by indexkeys */
490-
491-
if (clausegroup_list!=NIL)
511+
/*
512+
* if no join clause was matched then there ain't clauses for
513+
* joins at all.
514+
*/
515+
if (!jfound)
492516
{
493-
/*
494-
* if no join clause was matched then there ain't clauses for
495-
* joins at all.
496-
*/
497-
if (!jfound)
498-
{
499-
freeList(clausegroup_list);
500-
returnNIL;
501-
}
502-
returnlcons(clausegroup_list,NIL);
517+
freeList(clausegroup_list);
518+
returnNIL;
503519
}
504-
returnNIL;
520+
521+
/* clausegroup_list holds all matched clauses ordered by indexkeys */
522+
returnclausegroup_list;
505523
}
506524

507525

@@ -1150,41 +1168,22 @@ indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
11501168
foreach(i,joininfo_list)
11511169
{
11521170
JoinInfo*joininfo= (JoinInfo*)lfirst(i);
1153-
List*clausegroups;
1154-
1155-
if (joininfo->jinfo_restrictinfo==NIL)
1156-
continue;
1157-
clausegroups=group_clauses_by_ikey_for_joins(rel,
1158-
index,
1159-
index->indexkeys,
1160-
index->classlist,
1171+
List*clausegroup;
1172+
1173+
clausegroup=group_clauses_by_ikey_for_joins(rel,
1174+
index,
1175+
index->indexkeys,
1176+
index->classlist,
11611177
joininfo->jinfo_restrictinfo,
1162-
restrictinfo_list);
1163-
1164-
/*----------
1165-
* This code knows that group_clauses_by_ikey_for_joins() returns
1166-
* either NIL or a list containing a single sublist of clauses.
1167-
* The line
1168-
*cg_list = nconc(cg_list, clausegroups);
1169-
* is better read as
1170-
*cg_list = lappend(cg_list, lfirst(clausegroups));
1171-
* That is, we are appending the only sublist returned by
1172-
* group_clauses_by_ikey_for_joins() to the list of clause sublists
1173-
* that this routine will return. By using nconc() we recycle
1174-
* a cons cell that would be wasted ... whoever wrote this code
1175-
* was too clever by half...
1176-
*----------
1177-
*/
1178-
if (clausegroups!=NIL)
1178+
restrictinfo_list);
1179+
1180+
if (clausegroup!=NIL)
11791181
{
1180-
cg_list=nconc(cg_list,clausegroups);
1182+
cg_list=lappend(cg_list,clausegroup);
11811183
relid_list=lappend(relid_list,joininfo->unjoined_relids);
11821184
}
11831185
}
11841186

1185-
/* Make sure above clever code didn't screw up */
1186-
Assert(length(cg_list)==length(relid_list));
1187-
11881187
*clausegroups=cg_list;
11891188
*outerrelids=relid_list;
11901189
}
@@ -1200,7 +1199,7 @@ indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
12001199
*
12011200
* 'rel' is the relation for which 'index' is defined
12021201
* 'clausegroup_list' is a list of lists of restrictinfo nodes which can use
1203-
* 'index' on their inner relation.
1202+
* 'index'. Each sublist refers to the same set of outer rels.
12041203
* 'outerrelids_list' is a list of the required outer rels for each group
12051204
* of join clauses.
12061205
*
@@ -1245,10 +1244,12 @@ index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
12451244
* therefore, both indexid and indexqual should be single-element
12461245
* lists.
12471246
*/
1247+
Assert(length(index->relids)==1);
12481248
pathnode->indexid=index->relids;
1249-
pathnode->indexkeys=index->indexkeys;
12501249
pathnode->indexqual=lcons(indexquals,NIL);
12511250

1251+
pathnode->indexkeys=index->indexkeys;
1252+
12521253
/* joinid saves the rels needed on the outer side of the join */
12531254
pathnode->path.joinid=lfirst(outerrelids_list);
12541255

@@ -1268,59 +1269,38 @@ index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
12681269
}
12691270

12701271
/*
1271-
* create_index_path_group
1272-
* Creates a list of index path nodes for each group of clauses
1273-
* (restriction or join) that can be used in conjunction with an index.
1274-
*
1275-
* 'rel' is the relation for which 'index' is defined
1276-
* 'clausegroup_list' is the list of clause groups (lists of restrictinfo
1277-
*nodes) grouped by mergejoinorder
1278-
* 'join' is a flag indicating whether or not the clauses are join
1279-
*clauses
1280-
*
1281-
* Returns a list of new index path nodes.
1272+
* useful_for_mergejoin
1273+
* Determine whether the given index can support a mergejoin based
1274+
* on any join clause within the given list. The clauses have already
1275+
* been found to be relevant to the index by indexable_joinclauses.
1276+
* We just need to check whether any are mergejoin material.
12821277
*
1278+
* 'index' is the index of interest.
1279+
* 'clausegroup_list' is a list of clause groups (sublists of restrictinfo
1280+
*nodes)
12831281
*/
1284-
staticList*
1285-
create_index_path_group(Query*root,
1286-
RelOptInfo*rel,
1287-
RelOptInfo*index,
1288-
List*clausegroup_list,
1289-
booljoin)
1282+
staticbool
1283+
useful_for_mergejoin(RelOptInfo*index,
1284+
List*clausegroup_list)
12901285
{
1291-
List*path_list=NIL;
12921286
List*i;
12931287

12941288
foreach(i,clausegroup_list)
12951289
{
12961290
List*clausegroup=lfirst(i);
1297-
boolusable= true;
1291+
List*j;
12981292

1299-
if (join)
1293+
foreach(j,clausegroup)
13001294
{
1301-
List*j;
1295+
RestrictInfo*restrictinfo= (RestrictInfo*)lfirst(j);
13021296

1303-
foreach(j,clausegroup)
1304-
{
1305-
RestrictInfo*restrictinfo= (RestrictInfo*)lfirst(j);
1306-
if (!(is_joinable((Node*)restrictinfo->clause)&&
1307-
equal_path_merge_ordering(index->ordering,
1308-
restrictinfo->mergejoinorder)))
1309-
{
1310-
usable= false;
1311-
break;
1312-
}
1313-
}
1314-
}
1315-
1316-
if (usable)
1317-
{
1318-
path_list=lappend(path_list,
1319-
create_index_path(root,rel,index,
1320-
clausegroup,join));
1297+
if (is_joinable((Node*)restrictinfo->clause)&&
1298+
equal_path_merge_ordering(index->ordering,
1299+
restrictinfo->mergejoinorder))
1300+
return true;
13211301
}
13221302
}
1323-
returnpath_list;
1303+
returnfalse;
13241304
}
13251305

13261306
/****************************************************************************

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp