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

Commit82b4dd3

Browse files
committed
Merge restrictlist_selectivity into clauselist_selectivity by
teaching the latter to accept either RestrictInfo nodes or bareclause expressions; and cache the selectivity result in the RestrictInfonode when possible. This extends the caching behavior of approx_selectivityto many more contexts, and should reduce duplicate selectivitycalculations.
1 parent21a1202 commit82b4dd3

File tree

12 files changed

+196
-200
lines changed

12 files changed

+196
-200
lines changed

‎src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.271 2004/01/0400:07:32 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.272 2004/01/0403:51:52 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1170,6 +1170,7 @@ _copyRestrictInfo(RestrictInfo *from)
11701170
COPY_NODE_FIELD(clause);
11711171
COPY_SCALAR_FIELD(ispusheddown);
11721172
COPY_SCALAR_FIELD(canjoin);
1173+
COPY_BITMAPSET_FIELD(clause_relids);
11731174
COPY_BITMAPSET_FIELD(left_relids);
11741175
COPY_BITMAPSET_FIELD(right_relids);
11751176
COPY_NODE_FIELD(orclause);

‎src/backend/nodes/outfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.224 2004/01/0400:07:32 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.225 2004/01/0403:51:52 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1075,6 +1075,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
10751075
WRITE_NODE_FIELD(clause);
10761076
WRITE_BOOL_FIELD(ispusheddown);
10771077
WRITE_BOOL_FIELD(canjoin);
1078+
WRITE_BITMAPSET_FIELD(clause_relids);
10781079
WRITE_BITMAPSET_FIELD(left_relids);
10791080
WRITE_BITMAPSET_FIELD(right_relids);
10801081
WRITE_NODE_FIELD(orclause);

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

Lines changed: 133 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.62 2003/12/29 21:44:49 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.63 2004/01/04 03:51:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -54,33 +54,13 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
5454
*ROUTINES TO COMPUTE SELECTIVITIES
5555
****************************************************************************/
5656

57-
/*
58-
* restrictlist_selectivity -
59-
* Compute the selectivity of an implicitly-ANDed list of RestrictInfo
60-
* clauses.
61-
*
62-
* This is the same as clauselist_selectivity except for the representation
63-
* of the clause list.
64-
*/
65-
Selectivity
66-
restrictlist_selectivity(Query*root,
67-
List*restrictinfo_list,
68-
intvarRelid,
69-
JoinTypejointype)
70-
{
71-
List*clauselist=get_actual_clauses(restrictinfo_list);
72-
Selectivityresult;
73-
74-
result=clauselist_selectivity(root,clauselist,varRelid,jointype);
75-
freeList(clauselist);
76-
returnresult;
77-
}
78-
7957
/*
8058
* clauselist_selectivity -
8159
* Compute the selectivity of an implicitly-ANDed list of boolean
8260
* expression clauses. The list can be empty, in which case 1.0
83-
* must be returned.
61+
* must be returned. List elements may be either RestrictInfos
62+
* or bare expression clauses --- the former is preferred since
63+
* it allows caching of results.
8464
*
8565
* See clause_selectivity() for the meaning of the additional parameters.
8666
*
@@ -133,64 +113,80 @@ clauselist_selectivity(Query *root,
133113
foreach(clist,clauses)
134114
{
135115
Node*clause= (Node*)lfirst(clist);
116+
RestrictInfo*rinfo;
136117
Selectivitys2;
137118

119+
/* Always compute the selectivity using clause_selectivity */
120+
s2=clause_selectivity(root,clause,varRelid,jointype);
121+
122+
/*
123+
* Check for being passed a RestrictInfo.
124+
*/
125+
if (IsA(clause,RestrictInfo))
126+
{
127+
rinfo= (RestrictInfo*)clause;
128+
clause= (Node*)rinfo->clause;
129+
}
130+
else
131+
rinfo=NULL;
132+
138133
/*
139134
* See if it looks like a restriction clause with a pseudoconstant
140135
* on one side. (Anything more complicated than that might not
141-
* behave in the simple way we are expecting.)
142-
*
143-
* NB: for consistency of results, this fragment of code had better
144-
* match what clause_selectivity() would do in the cases it
145-
* handles.
136+
* behave in the simple way we are expecting.) Most of the tests
137+
* here can be done more efficiently with rinfo than without.
146138
*/
147-
if (is_opclause(clause)&&
148-
(varRelid!=0||NumRelids(clause)==1))
139+
if (is_opclause(clause)&&length(((OpExpr*)clause)->args)==2)
149140
{
150141
OpExpr*expr= (OpExpr*)clause;
142+
boolvaronleft= true;
143+
boolok;
151144

152-
if (length(expr->args)==2)
145+
if (rinfo)
153146
{
154-
boolvaronleft= true;
147+
ok= (bms_membership(rinfo->clause_relids)==BMS_SINGLETON)&&
148+
(is_pseudo_constant_clause_relids(lsecond(expr->args),
149+
rinfo->right_relids)||
150+
(varonleft= false,
151+
is_pseudo_constant_clause_relids(lfirst(expr->args),
152+
rinfo->left_relids)));
153+
}
154+
else
155+
{
156+
ok= (NumRelids(clause)==1)&&
157+
(is_pseudo_constant_clause(lsecond(expr->args))||
158+
(varonleft= false,
159+
is_pseudo_constant_clause(lfirst(expr->args))));
160+
}
155161

156-
if (is_pseudo_constant_clause(lsecond(expr->args))||
157-
(varonleft= false,
158-
is_pseudo_constant_clause(lfirst(expr->args))))
162+
if (ok)
163+
{
164+
/*
165+
* If it's not a "<" or ">" operator, just merge the
166+
* selectivity in generically. But if it's the
167+
* right oprrest, add the clause to rqlist for later
168+
* processing.
169+
*/
170+
switch (get_oprrest(expr->opno))
159171
{
160-
Oidopno=expr->opno;
161-
RegProcedureoprrest=get_oprrest(opno);
162-
163-
s2=restriction_selectivity(root,opno,
164-
expr->args,varRelid);
165-
166-
/*
167-
* If we reach here, we have computed the same result
168-
* that clause_selectivity would, so we can just use
169-
* s2 if it's the wrong oprrest. But if it's the
170-
* right oprrest, add the clause to rqlist for later
171-
* processing.
172-
*/
173-
switch (oprrest)
174-
{
175-
caseF_SCALARLTSEL:
176-
addRangeClause(&rqlist,clause,
177-
varonleft, true,s2);
178-
break;
179-
caseF_SCALARGTSEL:
180-
addRangeClause(&rqlist,clause,
181-
varonleft, false,s2);
182-
break;
183-
default:
184-
/* Just merge the selectivity in generically */
185-
s1=s1*s2;
186-
break;
187-
}
188-
continue;/* drop to loop bottom */
172+
caseF_SCALARLTSEL:
173+
addRangeClause(&rqlist,clause,
174+
varonleft, true,s2);
175+
break;
176+
caseF_SCALARGTSEL:
177+
addRangeClause(&rqlist,clause,
178+
varonleft, false,s2);
179+
break;
180+
default:
181+
/* Just merge the selectivity in generically */
182+
s1=s1*s2;
183+
break;
189184
}
185+
continue;/* drop to loop bottom */
190186
}
191187
}
188+
192189
/* Not the right form, so treat it generically. */
193-
s2=clause_selectivity(root,clause,varRelid,jointype);
194190
s1=s1*s2;
195191
}
196192

@@ -352,11 +348,39 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
352348
*rqlist=rqelem;
353349
}
354350

351+
/*
352+
* bms_is_subset_singleton
353+
*
354+
* Same result as bms_is_subset(s, bms_make_singleton(x)),
355+
* but a little faster and doesn't leak memory.
356+
*
357+
* Is this of use anywhere else? If so move to bitmapset.c ...
358+
*/
359+
staticbool
360+
bms_is_subset_singleton(constBitmapset*s,intx)
361+
{
362+
switch (bms_membership(s))
363+
{
364+
caseBMS_EMPTY_SET:
365+
return true;
366+
caseBMS_SINGLETON:
367+
returnbms_is_member(x,s);
368+
caseBMS_MULTIPLE:
369+
return false;
370+
}
371+
/* can't get here... */
372+
return false;
373+
}
374+
355375

356376
/*
357377
* clause_selectivity -
358378
* Compute the selectivity of a general boolean expression clause.
359379
*
380+
* The clause can be either a RestrictInfo or a plain expression. If it's
381+
* a RestrictInfo, we try to cache the selectivity for possible re-use,
382+
* so passing RestrictInfos is preferred.
383+
*
360384
* varRelid is either 0 or a rangetable index.
361385
*
362386
* When varRelid is not 0, only variables belonging to that relation are
@@ -379,9 +403,37 @@ clause_selectivity(Query *root,
379403
JoinTypejointype)
380404
{
381405
Selectivitys1=1.0;/* default for any unhandled clause type */
406+
RestrictInfo*rinfo=NULL;
407+
boolcacheable= false;
382408

383-
if (clause==NULL)
409+
if (clause==NULL)/* can this still happen? */
384410
returns1;
411+
412+
if (IsA(clause,RestrictInfo))
413+
{
414+
rinfo= (RestrictInfo*)clause;
415+
416+
/*
417+
* If possible, cache the result of the selectivity calculation for
418+
* the clause. We can cache if varRelid is zero or the clause
419+
* contains only vars of that relid --- otherwise varRelid will affect
420+
* the result, so mustn't cache. We ignore the possibility that
421+
* jointype will affect the result, which should be okay because outer
422+
* join clauses will always be examined with the same jointype value.
423+
*/
424+
if (varRelid==0||
425+
bms_is_subset_singleton(rinfo->clause_relids,varRelid))
426+
{
427+
/* Cacheable --- do we already have the result? */
428+
if (rinfo->this_selec >=0)
429+
returnrinfo->this_selec;
430+
cacheable= true;
431+
}
432+
433+
/* Proceed with examination of contained clause */
434+
clause= (Node*)rinfo->clause;
435+
}
436+
385437
if (IsA(clause,Var))
386438
{
387439
Var*var= (Var*)clause;
@@ -448,9 +500,10 @@ clause_selectivity(Query *root,
448500
elseif (or_clause(clause))
449501
{
450502
/*
451-
* Selectivities for an 'or' clause are computed as s1+s2 - s1*s2
452-
* to account for the probable overlap of selected tuple sets. XXX
453-
* is this too conservative?
503+
* Selectivities for an OR clause are computed as s1+s2 - s1*s2
504+
* to account for the probable overlap of selected tuple sets.
505+
*
506+
* XXX is this too conservative?
454507
*/
455508
List*arg;
456509

@@ -483,9 +536,13 @@ clause_selectivity(Query *root,
483536
{
484537
/*
485538
* Otherwise, it's a join if there's more than one relation
486-
* used.
539+
* used. We can optimize this calculation if an rinfo was passed.
487540
*/
488-
is_join_clause= (NumRelids(clause)>1);
541+
if (rinfo)
542+
is_join_clause= (bms_membership(rinfo->clause_relids)==
543+
BMS_MULTIPLE);
544+
else
545+
is_join_clause= (NumRelids(clause)>1);
489546
}
490547

491548
if (is_join_clause)
@@ -559,6 +616,10 @@ clause_selectivity(Query *root,
559616
jointype);
560617
}
561618

619+
/* Cache the result if possible */
620+
if (cacheable)
621+
rinfo->this_selec=s1;
622+
562623
#ifdefSELECTIVITY_DEBUG
563624
elog(DEBUG4,"clause_selectivity: s1 %f",s1);
564625
#endif/* SELECTIVITY_DEBUG */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp