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

Commit78296c2

Browse files
committed
Further cleanup for OR-of-AND WHERE-clauses. orindxpath can now handle
extracting from an AND subclause just those opclauses that are relevantfor a particular index. For example, we can now consider using an indexon x to process WHERE (x = 1 AND y = 2) OR (x = 2 AND y = 4) OR ...
1 parentdd14cd6 commit78296c2

File tree

3 files changed

+102
-62
lines changed

3 files changed

+102
-62
lines changed

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

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.78 2000/01/26 05:56:34 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.79 2000/02/05 18:26:09 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -51,15 +51,12 @@ typedef enum {
5151
}Prefix_Status;
5252

5353
staticvoidmatch_index_orclauses(RelOptInfo*rel,IndexOptInfo*index,
54-
intindexkey,Oidopclass,
5554
List*restrictinfo_list);
5655
staticList*match_index_orclause(RelOptInfo*rel,IndexOptInfo*index,
57-
intindexkey,Oidopclass,
5856
List*or_clauses,
5957
List*other_matching_indices);
6058
staticboolmatch_or_subclause_to_indexkey(RelOptInfo*rel,
6159
IndexOptInfo*index,
62-
intindexkey,Oidopclass,
6360
Expr*clause);
6461
staticList*group_clauses_by_indexkey(RelOptInfo*rel,IndexOptInfo*index,
6562
int*indexkeys,Oid*classes,
@@ -174,20 +171,11 @@ create_index_paths(Query *root,
174171
* so we can't build a path for an 'or' clause until all indexes have
175172
* been matched against it.)
176173
*
177-
* We currently only look to match the first key of each index against
178-
* 'or' subclauses. There are cases where a later key of a multi-key
179-
* index could be used (if other top-level clauses match earlier keys
180-
* of the index), but our poor brains are hurting already...
181-
*
182174
* We don't even think about special handling of 'or' clauses that
183175
* involve more than one relation (ie, are join clauses).
184176
* Can we do anything useful with those?
185177
*/
186-
match_index_orclauses(rel,
187-
index,
188-
index->indexkeys[0],
189-
index->classlist[0],
190-
restrictinfo_list);
178+
match_index_orclauses(rel,index,restrictinfo_list);
191179

192180
/*
193181
* 2. If the keys of this index match any of the available non-'or'
@@ -267,15 +255,11 @@ create_index_paths(Query *root,
267255
*
268256
* 'rel' is the node of the relation on which the index is defined.
269257
* 'index' is the index node.
270-
* 'indexkey' is the (single) key of the index that we will consider.
271-
* 'class' is the class of the operator corresponding to 'indexkey'.
272258
* 'restrictinfo_list' is the list of available restriction clauses.
273259
*/
274260
staticvoid
275261
match_index_orclauses(RelOptInfo*rel,
276262
IndexOptInfo*index,
277-
intindexkey,
278-
Oidopclass,
279263
List*restrictinfo_list)
280264
{
281265
List*i;
@@ -292,7 +276,6 @@ match_index_orclauses(RelOptInfo *rel,
292276
*/
293277
restrictinfo->subclauseindices=
294278
match_index_orclause(rel,index,
295-
indexkey,opclass,
296279
restrictinfo->clause->args,
297280
restrictinfo->subclauseindices);
298281
}
@@ -305,9 +288,12 @@ match_index_orclauses(RelOptInfo *rel,
305288
*
306289
* A match means that:
307290
* (1) the operator within the subclause can be used with the
308-
*index's specified operator class, and
291+
*index's specified operator class, and
309292
* (2) one operand of the subclause matches the index key.
310293
*
294+
* If a subclause is an 'and' clause, then it matches if any of its
295+
* subclauses is an opclause that matches.
296+
*
311297
* 'or_clauses' is the list of subclauses within the 'or' clause
312298
* 'other_matching_indices' is the list of information on other indices
313299
*that have already been matched to subclauses within this
@@ -323,8 +309,6 @@ match_index_orclauses(RelOptInfo *rel,
323309
staticList*
324310
match_index_orclause(RelOptInfo*rel,
325311
IndexOptInfo*index,
326-
intindexkey,
327-
Oidopclass,
328312
List*or_clauses,
329313
List*other_matching_indices)
330314
{
@@ -350,8 +334,7 @@ match_index_orclause(RelOptInfo *rel,
350334
{
351335
Expr*clause=lfirst(clist);
352336

353-
if (match_or_subclause_to_indexkey(rel,index,indexkey,opclass,
354-
clause))
337+
if (match_or_subclause_to_indexkey(rel,index,clause))
355338
{
356339
/* OK to add this index to sublist for this subclause */
357340
lfirst(matching_indices)=lcons(index,
@@ -368,33 +351,84 @@ match_index_orclause(RelOptInfo *rel,
368351
* See if a subclause of an OR clause matches an index.
369352
*
370353
* We accept the subclause if it is an operator clause that matches the
371-
* index, or if it is an AND clause all of whose members are operators
372-
* that match the index. (XXX Would accepting a single match be useful?)
354+
* index, or if it is an AND clause any of whose members is an opclause
355+
* that matches the index.
356+
*
357+
* We currently only look to match the first key of an index against
358+
* 'or' subclauses. There are cases where a later key of a multi-key
359+
* index could be used (if other top-level clauses match earlier keys
360+
* of the index), but our poor brains are hurting already...
373361
*/
374362
staticbool
375363
match_or_subclause_to_indexkey(RelOptInfo*rel,
376364
IndexOptInfo*index,
377-
intindexkey,
378-
Oidopclass,
379365
Expr*clause)
380366
{
367+
intindexkey=index->indexkeys[0];
368+
Oidopclass=index->classlist[0];
369+
381370
if (and_clause((Node*)clause))
382371
{
383372
List*item;
384373

385374
foreach(item,clause->args)
386375
{
387-
if (!match_clause_to_indexkey(rel,index,indexkey,opclass,
388-
lfirst(item), false))
389-
returnfalse;
376+
if (match_clause_to_indexkey(rel,index,indexkey,opclass,
377+
lfirst(item), false))
378+
returntrue;
390379
}
391-
returntrue;
380+
returnfalse;
392381
}
393382
else
394383
returnmatch_clause_to_indexkey(rel,index,indexkey,opclass,
395384
clause, false);
396385
}
397386

387+
/*
388+
* Given an OR subclause that has previously been determined to match
389+
* the specified index, extract a list of specific opclauses that can be
390+
* used as indexquals.
391+
*
392+
* In the simplest case this just means making a one-element list of the
393+
* given opclause. However, if the OR subclause is an AND, we have to
394+
* scan it to find the opclause(s) that match the index. (There should
395+
* be at least one, if match_or_subclause_to_indexkey succeeded, but there
396+
* could be more.) Also, we apply expand_indexqual_conditions() to convert
397+
* any special matching opclauses to indexable operators.
398+
*
399+
* The passed-in clause is not changed.
400+
*/
401+
List*
402+
extract_or_indexqual_conditions(RelOptInfo*rel,
403+
IndexOptInfo*index,
404+
Expr*orsubclause)
405+
{
406+
List*quals=NIL;
407+
intindexkey=index->indexkeys[0];
408+
Oidopclass=index->classlist[0];
409+
410+
if (and_clause((Node*)orsubclause))
411+
{
412+
List*item;
413+
414+
foreach(item,orsubclause->args)
415+
{
416+
if (match_clause_to_indexkey(rel,index,indexkey,opclass,
417+
lfirst(item), false))
418+
quals=lappend(quals,lfirst(item));
419+
}
420+
if (quals==NIL)
421+
elog(ERROR,"extract_or_indexqual_conditions: no matching clause");
422+
}
423+
else
424+
{
425+
/* we assume the caller passed a valid indexable qual */
426+
quals=lcons(orsubclause,NIL);
427+
}
428+
429+
returnexpand_indexqual_conditions(quals);
430+
}
431+
398432

399433
/****************************************************************************
400434
*---- ROUTINES TO CHECK RESTRICTIONS ----
@@ -614,8 +648,8 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
614648
*
615649
* Returns true if the clause can be used with this index key.
616650
*
617-
* NOTE: returns false if clause is an OR or AND clause;to the extent
618-
*we cope with those at all, it is done byhigher-level routines.
651+
* NOTE: returns false if clause is an OR or AND clause;it is the
652+
*responsibility ofhigher-level routines to cope with those.
619653
*/
620654
staticbool
621655
match_clause_to_indexkey(RelOptInfo*rel,

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

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.35 2000/01/26 05:56:34 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.36 2000/02/05 18:26:09 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
15-
#include"postgres.h"
16-
17-
1815

16+
#include"postgres.h"
1917

2018
#include"nodes/nodeFuncs.h"
2119
#include"optimizer/clauses.h"
@@ -33,7 +31,8 @@ static void best_or_subclause_indices(Query *root, RelOptInfo *rel,
3331
List**indexids,
3432
Cost*cost);
3533
staticvoidbest_or_subclause_index(Query*root,RelOptInfo*rel,
36-
List*indexqual,List*indices,
34+
Expr*subclause,List*indices,
35+
List**retIndexQual,
3736
Oid*retIndexid,
3837
Cost*retCost);
3938

@@ -43,7 +42,7 @@ static void best_or_subclause_index(Query *root, RelOptInfo *rel,
4342
* Creates index paths for indices that match 'or' clauses.
4443
* create_index_paths() must already have been called.
4544
*
46-
* 'rel' is the relation entry for which the paths are to bedefined on
45+
* 'rel' is the relation entry for which the paths are to becreated
4746
* 'clauses' is the list of available restriction clause nodes
4847
*
4948
* Returns a list of index path nodes.
@@ -164,21 +163,16 @@ best_or_subclause_indices(Query *root,
164163
foreach(slist,subclauses)
165164
{
166165
Expr*subclause=lfirst(slist);
167-
List*indexqual;
166+
List*best_indexqual;
168167
Oidbest_indexid;
169168
Costbest_cost;
170169

171-
/* Convert this 'or' subclause to an indexqual list */
172-
indexqual=make_ands_implicit(subclause);
173-
/* expand special operators to indexquals the executor can handle */
174-
indexqual=expand_indexqual_conditions(indexqual);
175-
176-
best_or_subclause_index(root,rel,indexqual,lfirst(indices),
177-
&best_indexid,&best_cost);
170+
best_or_subclause_index(root,rel,subclause,lfirst(indices),
171+
&best_indexqual,&best_indexid,&best_cost);
178172

179173
Assert(best_indexid!=InvalidOid);
180174

181-
*indexquals=lappend(*indexquals,indexqual);
175+
*indexquals=lappend(*indexquals,best_indexqual);
182176
*indexids=lappendi(*indexids,best_indexid);
183177
*cost+=best_cost;
184178

@@ -193,41 +187,49 @@ best_or_subclause_indices(Query *root,
193187
* the least expensive.
194188
*
195189
* 'rel' is the node of the relation on which the index is defined
196-
* 'indexqual' is theindexqual list derived from the subclause
190+
* 'subclause' is theOR subclause being considered
197191
* 'indices' is a list of IndexOptInfo nodes that match the subclause
192+
* '*retIndexQual' gets a list of the indexqual conditions for the best index
198193
* '*retIndexid' gets the OID of the best index
199194
* '*retCost' gets the cost of a scan with that index
200195
*/
201196
staticvoid
202197
best_or_subclause_index(Query*root,
203198
RelOptInfo*rel,
204-
List*indexqual,
199+
Expr*subclause,
205200
List*indices,
201+
List**retIndexQual,/* return value */
206202
Oid*retIndexid,/* return value */
207203
Cost*retCost)/* return value */
208204
{
209-
boolfirst_run= true;
205+
boolfirst_time= true;
210206
List*ilist;
211207

212208
/* if we don't match anything, return zeros */
209+
*retIndexQual=NIL;
213210
*retIndexid=InvalidOid;
214211
*retCost=0.0;
215212

216213
foreach(ilist,indices)
217214
{
218215
IndexOptInfo*index= (IndexOptInfo*)lfirst(ilist);
216+
List*indexqual;
219217
Costsubcost;
220218

221219
Assert(IsA(index,IndexOptInfo));
222220

221+
/* Convert this 'or' subclause to an indexqual list */
222+
indexqual=extract_or_indexqual_conditions(rel,index,subclause);
223+
223224
subcost=cost_index(root,rel,index,indexqual,
224225
false);
225226

226-
if (first_run||subcost<*retCost)
227+
if (first_time||subcost<*retCost)
227228
{
229+
*retIndexQual=indexqual;
228230
*retIndexid=index->indexoid;
229231
*retCost=subcost;
230-
first_run= false;
232+
first_time= false;
231233
}
232234
}
233235
}

‎src/include/optimizer/paths.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $Id: paths.h,v 1.39 2000/01/26 05:58:20 momjian Exp $
11+
* $Id: paths.h,v 1.40 2000/02/05 18:26:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -38,8 +38,18 @@ extern List *create_index_paths(Query *root, RelOptInfo *rel, List *indices,
3838
List*joininfo_list);
3939
externOidindexable_operator(Expr*clause,Oidopclass,Oidrelam,
4040
boolindexkey_on_left);
41+
externList*extract_or_indexqual_conditions(RelOptInfo*rel,
42+
IndexOptInfo*index,
43+
Expr*orsubclause);
4144
externList*expand_indexqual_conditions(List*indexquals);
4245

46+
/*
47+
* orindxpath.c
48+
* additional routines for indexable OR clauses
49+
*/
50+
externList*create_or_index_paths(Query*root,RelOptInfo*rel,
51+
List*clauses);
52+
4353
/*
4454
* tidpath.h
4555
* routines to generate tid paths
@@ -52,12 +62,6 @@ extern List *create_tidscan_paths(Query *root, RelOptInfo *rel);
5262
*/
5363
externvoidupdate_rels_pathlist_for_joins(Query*root,List*joinrels);
5464

55-
56-
/*
57-
* orindxpath.c
58-
*/
59-
externList*create_or_index_paths(Query*root,RelOptInfo*rel,List*clauses);
60-
6165
/*
6266
* pathkeys.c
6367
* utilities for matching and building path keys
@@ -100,7 +104,7 @@ extern bool nonoverlap_sets(List *s1, List *s2);
100104
externboolis_subset(List*s1,List*s2);
101105

102106
/*
103-
*prototypes for path/prune.c
107+
* prune.c
104108
*/
105109
externvoidmerge_rels_with_same_relids(List*rel_list);
106110
externvoidrels_set_cheapest(Query*root,List*rel_list);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp