00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "catalog/pg_operator.h"
00018 #include "nodes/makefuncs.h"
00019 #include "optimizer/clauses.h"
00020 #include "optimizer/cost.h"
00021 #include "optimizer/pathnode.h"
00022 #include "optimizer/plancat.h"
00023 #include "utils/fmgroids.h"
00024 #include "utils/lsyscache.h"
00025 #include "utils/selfuncs.h"
00026
00027
00028
00029
00030
00031
00032 typedef struct RangeQueryClause
00033 {
00034 struct RangeQueryClause *next;
00035 Node *var;
00036 bool have_lobound;
00037 bool have_hibound;
00038 Selectivity lobound;
00039 Selectivity hibound;
00040 } RangeQueryClause;
00041
00042 static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
00043 bool varonleft, bool isLTsel, Selectivity s2);
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 Selectivity
00093 clauselist_selectivity(PlannerInfo *root,
00094 List *clauses,
00095 int varRelid,
00096 JoinType jointype,
00097 SpecialJoinInfo *sjinfo)
00098 {
00099 Selectivity s1 = 1.0;
00100 RangeQueryClause *rqlist = NULL;
00101 ListCell *l;
00102
00103
00104
00105
00106
00107 if (list_length(clauses) == 1)
00108 return clause_selectivity(root, (Node *) linitial(clauses),
00109 varRelid, jointype, sjinfo);
00110
00111
00112
00113
00114
00115
00116 foreach(l, clauses)
00117 {
00118 Node *clause = (Node *) lfirst(l);
00119 RestrictInfo *rinfo;
00120 Selectivity s2;
00121
00122
00123 s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
00124
00125
00126
00127
00128
00129
00130
00131 if (IsA(clause, RestrictInfo))
00132 {
00133 rinfo = (RestrictInfo *) clause;
00134 if (rinfo->pseudoconstant)
00135 {
00136 s1 = s1 * s2;
00137 continue;
00138 }
00139 clause = (Node *) rinfo->clause;
00140 }
00141 else
00142 rinfo = NULL;
00143
00144
00145
00146
00147
00148
00149
00150 if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
00151 {
00152 OpExpr *expr = (OpExpr *) clause;
00153 bool varonleft = true;
00154 bool ok;
00155
00156 if (rinfo)
00157 {
00158 ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
00159 (is_pseudo_constant_clause_relids(lsecond(expr->args),
00160 rinfo->right_relids) ||
00161 (varonleft = false,
00162 is_pseudo_constant_clause_relids(linitial(expr->args),
00163 rinfo->left_relids)));
00164 }
00165 else
00166 {
00167 ok = (NumRelids(clause) == 1) &&
00168 (is_pseudo_constant_clause(lsecond(expr->args)) ||
00169 (varonleft = false,
00170 is_pseudo_constant_clause(linitial(expr->args))));
00171 }
00172
00173 if (ok)
00174 {
00175
00176
00177
00178
00179
00180 switch (get_oprrest(expr->opno))
00181 {
00182 case F_SCALARLTSEL:
00183 addRangeClause(&rqlist, clause,
00184 varonleft, true, s2);
00185 break;
00186 case F_SCALARGTSEL:
00187 addRangeClause(&rqlist, clause,
00188 varonleft, false, s2);
00189 break;
00190 default:
00191
00192 s1 = s1 * s2;
00193 break;
00194 }
00195 continue;
00196 }
00197 }
00198
00199
00200 s1 = s1 * s2;
00201 }
00202
00203
00204
00205
00206 while (rqlist != NULL)
00207 {
00208 RangeQueryClause *rqnext;
00209
00210 if (rqlist->have_lobound && rqlist->have_hibound)
00211 {
00212
00213 Selectivity s2;
00214
00215
00216
00217
00218
00219
00220 if (rqlist->hibound == DEFAULT_INEQ_SEL ||
00221 rqlist->lobound == DEFAULT_INEQ_SEL)
00222 {
00223 s2 = DEFAULT_RANGE_INEQ_SEL;
00224 }
00225 else
00226 {
00227 s2 = rqlist->hibound + rqlist->lobound - 1.0;
00228
00229
00230 s2 += nulltestsel(root, IS_NULL, rqlist->var,
00231 varRelid, jointype, sjinfo);
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 if (s2 <= 0.0)
00242 {
00243 if (s2 < -0.01)
00244 {
00245
00246
00247
00248
00249 s2 = DEFAULT_RANGE_INEQ_SEL;
00250 }
00251 else
00252 {
00253
00254
00255
00256
00257 s2 = 1.0e-10;
00258 }
00259 }
00260 }
00261
00262 s1 *= s2;
00263 }
00264 else
00265 {
00266
00267 if (rqlist->have_lobound)
00268 s1 *= rqlist->lobound;
00269 else
00270 s1 *= rqlist->hibound;
00271 }
00272
00273 rqnext = rqlist->next;
00274 pfree(rqlist);
00275 rqlist = rqnext;
00276 }
00277
00278 return s1;
00279 }
00280
00281
00282
00283
00284
00285
00286 static void
00287 addRangeClause(RangeQueryClause **rqlist, Node *clause,
00288 bool varonleft, bool isLTsel, Selectivity s2)
00289 {
00290 RangeQueryClause *rqelem;
00291 Node *var;
00292 bool is_lobound;
00293
00294 if (varonleft)
00295 {
00296 var = get_leftop((Expr *) clause);
00297 is_lobound = !isLTsel;
00298 }
00299 else
00300 {
00301 var = get_rightop((Expr *) clause);
00302 is_lobound = isLTsel;
00303 }
00304
00305 for (rqelem = *rqlist; rqelem; rqelem = rqelem->next)
00306 {
00307
00308
00309
00310
00311 if (!equal(var, rqelem->var))
00312 continue;
00313
00314 if (is_lobound)
00315 {
00316 if (!rqelem->have_lobound)
00317 {
00318 rqelem->have_lobound = true;
00319 rqelem->lobound = s2;
00320 }
00321 else
00322 {
00323
00324
00325
00326
00327
00328
00329
00330 if (rqelem->lobound > s2)
00331 rqelem->lobound = s2;
00332 }
00333 }
00334 else
00335 {
00336 if (!rqelem->have_hibound)
00337 {
00338 rqelem->have_hibound = true;
00339 rqelem->hibound = s2;
00340 }
00341 else
00342 {
00343
00344
00345
00346
00347
00348
00349
00350 if (rqelem->hibound > s2)
00351 rqelem->hibound = s2;
00352 }
00353 }
00354 return;
00355 }
00356
00357
00358 rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
00359 rqelem->var = var;
00360 if (is_lobound)
00361 {
00362 rqelem->have_lobound = true;
00363 rqelem->have_hibound = false;
00364 rqelem->lobound = s2;
00365 }
00366 else
00367 {
00368 rqelem->have_lobound = false;
00369 rqelem->have_hibound = true;
00370 rqelem->hibound = s2;
00371 }
00372 rqelem->next = *rqlist;
00373 *rqlist = rqelem;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 static bool
00385 bms_is_subset_singleton(const Bitmapset *s, int x)
00386 {
00387 switch (bms_membership(s))
00388 {
00389 case BMS_EMPTY_SET:
00390 return true;
00391 case BMS_SINGLETON:
00392 return bms_is_member(x, s);
00393 case BMS_MULTIPLE:
00394 return false;
00395 }
00396
00397 return false;
00398 }
00399
00400
00401
00402
00403
00404
00405 static inline bool
00406 treat_as_join_clause(Node *clause, RestrictInfo *rinfo,
00407 int varRelid, SpecialJoinInfo *sjinfo)
00408 {
00409 if (varRelid != 0)
00410 {
00411
00412
00413
00414
00415 return false;
00416 }
00417 else if (sjinfo == NULL)
00418 {
00419
00420
00421
00422
00423 return false;
00424 }
00425 else
00426 {
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 if (rinfo)
00438 return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
00439 else
00440 return (NumRelids(clause) > 1);
00441 }
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 Selectivity
00484 clause_selectivity(PlannerInfo *root,
00485 Node *clause,
00486 int varRelid,
00487 JoinType jointype,
00488 SpecialJoinInfo *sjinfo)
00489 {
00490 Selectivity s1 = 0.5;
00491 RestrictInfo *rinfo = NULL;
00492 bool cacheable = false;
00493
00494 if (clause == NULL)
00495 return s1;
00496
00497 if (IsA(clause, RestrictInfo))
00498 {
00499 rinfo = (RestrictInfo *) clause;
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 if (rinfo->pseudoconstant)
00510 {
00511 if (!IsA(rinfo->clause, Const))
00512 return (Selectivity) 1.0;
00513 }
00514
00515
00516
00517
00518 if (rinfo->norm_selec > 1)
00519 return (Selectivity) 1.0;
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 if (varRelid == 0 ||
00533 bms_is_subset_singleton(rinfo->clause_relids, varRelid))
00534 {
00535
00536 if (jointype == JOIN_INNER)
00537 {
00538 if (rinfo->norm_selec >= 0)
00539 return rinfo->norm_selec;
00540 }
00541 else
00542 {
00543 if (rinfo->outer_selec >= 0)
00544 return rinfo->outer_selec;
00545 }
00546 cacheable = true;
00547 }
00548
00549
00550
00551
00552
00553
00554 if (rinfo->orclause)
00555 clause = (Node *) rinfo->orclause;
00556 else
00557 clause = (Node *) rinfo->clause;
00558 }
00559
00560 if (IsA(clause, Var))
00561 {
00562 Var *var = (Var *) clause;
00563
00564
00565
00566
00567
00568 if (var->varlevelsup == 0 &&
00569 (varRelid == 0 || varRelid == (int) var->varno))
00570 {
00571
00572
00573
00574
00575
00576 s1 = restriction_selectivity(root,
00577 BooleanEqualOperator,
00578 list_make2(var,
00579 makeBoolConst(true,
00580 false)),
00581 InvalidOid,
00582 varRelid);
00583 }
00584 }
00585 else if (IsA(clause, Const))
00586 {
00587
00588 Const *con = (Const *) clause;
00589
00590 s1 = con->constisnull ? 0.0 :
00591 DatumGetBool(con->constvalue) ? 1.0 : 0.0;
00592 }
00593 else if (IsA(clause, Param))
00594 {
00595
00596 Node *subst = estimate_expression_value(root, clause);
00597
00598 if (IsA(subst, Const))
00599 {
00600
00601 Const *con = (Const *) subst;
00602
00603 s1 = con->constisnull ? 0.0 :
00604 DatumGetBool(con->constvalue) ? 1.0 : 0.0;
00605 }
00606 else
00607 {
00608
00609 }
00610 }
00611 else if (not_clause(clause))
00612 {
00613
00614 s1 = 1.0 - clause_selectivity(root,
00615 (Node *) get_notclausearg((Expr *) clause),
00616 varRelid,
00617 jointype,
00618 sjinfo);
00619 }
00620 else if (and_clause(clause))
00621 {
00622
00623 s1 = clauselist_selectivity(root,
00624 ((BoolExpr *) clause)->args,
00625 varRelid,
00626 jointype,
00627 sjinfo);
00628 }
00629 else if (or_clause(clause))
00630 {
00631
00632
00633
00634
00635
00636
00637 ListCell *arg;
00638
00639 s1 = 0.0;
00640 foreach(arg, ((BoolExpr *) clause)->args)
00641 {
00642 Selectivity s2 = clause_selectivity(root,
00643 (Node *) lfirst(arg),
00644 varRelid,
00645 jointype,
00646 sjinfo);
00647
00648 s1 = s1 + s2 - s1 * s2;
00649 }
00650 }
00651 else if (is_opclause(clause) || IsA(clause, DistinctExpr))
00652 {
00653 OpExpr *opclause = (OpExpr *) clause;
00654 Oid opno = opclause->opno;
00655
00656 if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
00657 {
00658
00659 s1 = join_selectivity(root, opno,
00660 opclause->args,
00661 opclause->inputcollid,
00662 jointype,
00663 sjinfo);
00664 }
00665 else
00666 {
00667
00668 s1 = restriction_selectivity(root, opno,
00669 opclause->args,
00670 opclause->inputcollid,
00671 varRelid);
00672 }
00673
00674
00675
00676
00677
00678
00679
00680 if (IsA(clause, DistinctExpr))
00681 s1 = 1.0 - s1;
00682 }
00683 else if (is_funcclause(clause))
00684 {
00685
00686
00687
00688
00689
00690 s1 = (Selectivity) 0.3333333;
00691 }
00692 #ifdef NOT_USED
00693 else if (IsA(clause, SubPlan) ||
00694 IsA(clause, AlternativeSubPlan))
00695 {
00696
00697
00698
00699 s1 = (Selectivity) 0.5;
00700 }
00701 #endif
00702 else if (IsA(clause, ScalarArrayOpExpr))
00703 {
00704
00705 s1 = scalararraysel(root,
00706 (ScalarArrayOpExpr *) clause,
00707 treat_as_join_clause(clause, rinfo,
00708 varRelid, sjinfo),
00709 varRelid,
00710 jointype,
00711 sjinfo);
00712 }
00713 else if (IsA(clause, RowCompareExpr))
00714 {
00715
00716 s1 = rowcomparesel(root,
00717 (RowCompareExpr *) clause,
00718 varRelid,
00719 jointype,
00720 sjinfo);
00721 }
00722 else if (IsA(clause, NullTest))
00723 {
00724
00725 s1 = nulltestsel(root,
00726 ((NullTest *) clause)->nulltesttype,
00727 (Node *) ((NullTest *) clause)->arg,
00728 varRelid,
00729 jointype,
00730 sjinfo);
00731 }
00732 else if (IsA(clause, BooleanTest))
00733 {
00734
00735 s1 = booltestsel(root,
00736 ((BooleanTest *) clause)->booltesttype,
00737 (Node *) ((BooleanTest *) clause)->arg,
00738 varRelid,
00739 jointype,
00740 sjinfo);
00741 }
00742 else if (IsA(clause, CurrentOfExpr))
00743 {
00744
00745 CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
00746 RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
00747
00748 if (crel->tuples > 0)
00749 s1 = 1.0 / crel->tuples;
00750 }
00751 else if (IsA(clause, RelabelType))
00752 {
00753
00754 s1 = clause_selectivity(root,
00755 (Node *) ((RelabelType *) clause)->arg,
00756 varRelid,
00757 jointype,
00758 sjinfo);
00759 }
00760 else if (IsA(clause, CoerceToDomain))
00761 {
00762
00763 s1 = clause_selectivity(root,
00764 (Node *) ((CoerceToDomain *) clause)->arg,
00765 varRelid,
00766 jointype,
00767 sjinfo);
00768 }
00769
00770
00771 if (cacheable)
00772 {
00773 if (jointype == JOIN_INNER)
00774 rinfo->norm_selec = s1;
00775 else
00776 rinfo->outer_selec = s1;
00777 }
00778
00779 #ifdef SELECTIVITY_DEBUG
00780 elog(DEBUG4, "clause_selectivity: s1 %f", s1);
00781 #endif
00782
00783 return s1;
00784 }