pathnode.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:18k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * pathnode.c
  4.  *   Routines to manipulate pathlists and create path nodes
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.42.2.1 1999/08/02 06:27:08 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <math.h>
  15. #include "postgres.h"
  16. #include "optimizer/cost.h"
  17. #include "optimizer/keys.h"
  18. #include "optimizer/ordering.h"
  19. #include "optimizer/pathnode.h"
  20. #include "optimizer/paths.h"
  21. #include "optimizer/plancat.h"
  22. #include "optimizer/restrictinfo.h"
  23. #include "parser/parsetree.h"
  24. static Path *better_path(Path *new_path, List *unique_paths, bool *is_new);
  25. /*****************************************************************************
  26.  * MISC. PATH UTILITIES
  27.  *****************************************************************************/
  28. /*
  29.  * path_is_cheaper
  30.  *   Returns t iff 'path1' is cheaper than 'path2'.
  31.  *
  32.  */
  33. bool
  34. path_is_cheaper(Path *path1, Path *path2)
  35. {
  36. Cost cost1 = path1->path_cost;
  37. Cost cost2 = path2->path_cost;
  38. return (bool) (cost1 < cost2);
  39. }
  40. /*
  41.  * set_cheapest
  42.  *   Finds the minimum cost path from among a relation's paths.
  43.  *
  44.  * 'parent_rel' is the parent relation
  45.  * 'pathlist' is a list of path nodes corresponding to 'parent_rel'
  46.  *
  47.  * Returns and sets the relation entry field with the pathnode that
  48.  * is minimum.
  49.  *
  50.  */
  51. Path *
  52. set_cheapest(RelOptInfo *parent_rel, List *pathlist)
  53. {
  54. List    *p;
  55. Path    *cheapest_so_far;
  56. Assert(pathlist != NIL);
  57. Assert(IsA(parent_rel, RelOptInfo));
  58. cheapest_so_far = (Path *) lfirst(pathlist);
  59. foreach(p, lnext(pathlist))
  60. {
  61. Path    *path = (Path *) lfirst(p);
  62. if (path_is_cheaper(path, cheapest_so_far))
  63. cheapest_so_far = path;
  64. }
  65. parent_rel->cheapestpath = cheapest_so_far;
  66. return cheapest_so_far;
  67. }
  68. /*
  69.  * add_pathlist
  70.  *   For each path in the list 'new_paths', add to the list 'unique_paths'
  71.  *   only those paths that are unique (i.e., unique ordering and ordering
  72.  *   keys).  Should a conflict arise, the more expensive path is thrown out,
  73.  *   thereby pruning the plan space.  But we don't prune if xfunc
  74.  *   told us not to.
  75.  *
  76.  * 'parent_rel' is the relation entry to which these paths correspond.
  77.  *
  78.  * Returns the list of unique pathnodes.
  79.  *
  80.  */
  81. List *
  82. add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths)
  83. {
  84. List    *p1;
  85. foreach(p1, new_paths)
  86. {
  87. Path    *new_path = (Path *) lfirst(p1);
  88. Path    *old_path;
  89. bool is_new;
  90. /* Is this new path already in unique_paths? */
  91. if (member(new_path, unique_paths))
  92. continue;
  93. /* Find best matching path */
  94. old_path = better_path(new_path, unique_paths, &is_new);
  95. if (is_new)
  96. {
  97. /* This is a brand new path.  */
  98. new_path->parent = parent_rel;
  99. unique_paths = lcons(new_path, unique_paths);
  100. }
  101. else if (old_path == NULL)
  102. {
  103. ; /* do nothing if path is not cheaper */
  104. }
  105. else if (old_path != NULL)
  106. { /* (IsA(old_path,Path)) { */
  107. new_path->parent = parent_rel;
  108. if (!parent_rel->pruneable)
  109. unique_paths = lcons(new_path, unique_paths);
  110. else
  111. unique_paths = lcons(new_path,
  112.  LispRemove(old_path, unique_paths));
  113. }
  114. }
  115. return unique_paths;
  116. }
  117. /*
  118.  * better_path
  119.  *   Determines whether 'new_path' has the same ordering and keys as some
  120.  *   path in the list 'unique_paths'. If there is a redundant path,
  121.  *   eliminate the more expensive path.
  122.  *
  123.  * Returns:
  124.  *   The old path - if 'new_path' matches some path in 'unique_paths' and is
  125.  * cheaper
  126.  *   nil - if 'new_path' matches but isn't cheaper
  127.  *   t - if there is no path in the list with the same ordering and keys
  128.  *
  129.  */
  130. static Path *
  131. better_path(Path *new_path, List *unique_paths, bool *is_new)
  132. {
  133. Path    *path = (Path *) NULL;
  134. List    *temp = NIL;
  135. int better_key;
  136. int better_sort;
  137. #ifdef OPTDUP_DEBUG
  138. printf("better_path entryn");
  139. printf("newn");
  140. pprint(new_path);
  141. printf("unique_pathsn");
  142. pprint(unique_paths);
  143. #endif
  144. foreach(temp, unique_paths)
  145. {
  146. path = (Path *) lfirst(temp);
  147. #ifdef OPTDUP_DEBUG
  148. if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &better_key) ||
  149. better_key != 0)
  150. {
  151. printf("betterkey = %dn", better_key);
  152. printf("newpathn");
  153. pprint(new_path->pathkeys);
  154. printf("oldpathn");
  155. pprint(path->pathkeys);
  156. if (path->pathkeys && new_path->pathkeys &&
  157. length(lfirst(path->pathkeys)) >= 2 /* &&
  158.  * length(lfirst(path->pa
  159.  * thkeys)) <
  160.  * length(lfirst(new_path
  161. ->pathkeys)) */ )
  162. sleep(0); /* set breakpoint here */
  163. }
  164. if (!pathorder_match(new_path->pathorder, path->pathorder,
  165.  &better_sort) ||
  166. better_sort != 0)
  167. {
  168. printf("newordn");
  169. pprint(new_path->pathorder);
  170. printf("oldordn");
  171. pprint(path->pathorder);
  172. }
  173. #endif
  174. if (pathkeys_match(new_path->pathkeys, path->pathkeys,
  175.    &better_key) &&
  176. pathorder_match(new_path->pathorder, path->pathorder,
  177. &better_sort))
  178. {
  179. /*
  180.  * Replace pathkeys that match exactly, {{1,2}}, {{1,2}}
  181.  * Replace pathkeys {{1,2}} with {{1,2,3}}} if the latter is
  182.  * not more expensive and replace unordered path with ordered
  183.  * path if it is not more expensive.  Favor sorted keys over
  184.  * unsorted keys in the same way.
  185.  */
  186. /* same keys, and new is cheaper, use it */
  187. if ((better_key == 0 && better_sort == 0 &&
  188.  new_path->path_cost < path->path_cost) ||
  189. /* new is better, and cheaper, use it */
  190. (((better_key == 1 && better_sort != 2) ||
  191.   (better_key != 2 && better_sort == 1)) &&
  192.  new_path->path_cost <= path->path_cost))
  193. {
  194. #ifdef OPTDUP_DEBUG
  195. printf("replace with new %p old %p better key %d better sort %dn", &new_path, &path, better_key, better_sort);
  196. printf("newn");
  197. pprint(new_path);
  198. printf("oldn");
  199. pprint(path);
  200. #endif
  201. *is_new = false;
  202. return path;
  203. }
  204. /* same keys, new is more expensive, stop */
  205. if ((better_key == 0 && better_sort == 0 &&
  206.  new_path->path_cost >= path->path_cost) ||
  207. /* old is better, and less expensive, stop */
  208. (((better_key == 2 && better_sort != 1) ||
  209.   (better_key != 1 && better_sort == 2)) &&
  210.  new_path->path_cost >= path->path_cost))
  211. {
  212. #ifdef OPTDUP_DEBUG
  213. printf("skip new %p old %p better key %d better sort %dn", &new_path, &path, better_key, better_sort);
  214. printf("newn");
  215. pprint(new_path);
  216. printf("oldn");
  217. pprint(path);
  218. #endif
  219. *is_new = false;
  220. return NULL;
  221. }
  222. }
  223. }
  224. #ifdef OPTDUP_DEBUG
  225. printf("add new %p old %p better key %d better sort %dn", &new_path, &path, better_key, better_sort);
  226. printf("newn");
  227. pprint(new_path);
  228. #endif
  229. *is_new = true;
  230. return NULL;
  231. }
  232. /*****************************************************************************
  233.  * PATH NODE CREATION ROUTINES
  234.  *****************************************************************************/
  235. /*
  236.  * create_seqscan_path
  237.  *   Creates a path corresponding to a sequential scan, returning the
  238.  *   pathnode.
  239.  *
  240.  */
  241. Path *
  242. create_seqscan_path(RelOptInfo *rel)
  243. {
  244. int relid = 0;
  245. Path    *pathnode = makeNode(Path);
  246. pathnode->pathtype = T_SeqScan;
  247. pathnode->parent = rel;
  248. pathnode->path_cost = 0.0;
  249. pathnode->pathorder = makeNode(PathOrder);
  250. pathnode->pathorder->ordtype = SORTOP_ORDER;
  251. pathnode->pathorder->ord.sortop = NULL;
  252. pathnode->pathkeys = NIL;
  253. /*
  254.  * copy restrictinfo list into path for expensive function processing
  255.  * JMH, 7/7/92
  256.  */
  257. pathnode->loc_restrictinfo = (List *) copyObject((Node *) rel->restrictinfo);
  258. if (rel->relids != NULL)
  259. relid = lfirsti(rel->relids);
  260. pathnode->path_cost = cost_seqscan(relid,
  261.    rel->pages, rel->tuples);
  262. /* add in expensive functions cost!  -- JMH, 7/7/92 */
  263. #ifdef NOT_USED
  264. if (XfuncMode != XFUNC_OFF)
  265. pathnode->path_cost += xfunc_get_path_cost(pathnode);
  266. #endif
  267. return pathnode;
  268. }
  269. /*
  270.  * create_index_path
  271.  *   Creates a single path node for an index scan.
  272.  *
  273.  * 'rel' is the parent rel
  274.  * 'index' is the pathnode for the index on 'rel'
  275.  * 'restriction_clauses' is a list of restriction clause nodes.
  276.  * 'is_join_scan' is a flag indicating whether or not the index is being
  277.  * considered because of its sort order.
  278.  *
  279.  * Returns the new path node.
  280.  *
  281.  */
  282. IndexPath  *
  283. create_index_path(Query *root,
  284.   RelOptInfo *rel,
  285.   RelOptInfo *index,
  286.   List *restriction_clauses,
  287.   bool is_join_scan)
  288. {
  289. IndexPath  *pathnode = makeNode(IndexPath);
  290. pathnode->path.pathtype = T_IndexScan;
  291. pathnode->path.parent = rel;
  292. pathnode->path.pathorder = makeNode(PathOrder);
  293. pathnode->path.pathorder->ordtype = SORTOP_ORDER;
  294. pathnode->path.pathorder->ord.sortop = index->ordering;
  295. pathnode->indexid = index->relids;
  296. pathnode->indexkeys = index->indexkeys;
  297. pathnode->indexqual = NIL;
  298. /*
  299.  * copy restrictinfo list into path for expensive function processing
  300.  * JMH, 7/7/92
  301.  */
  302. pathnode->path.loc_restrictinfo = set_difference((List *) copyObject((Node *) rel->restrictinfo),
  303.    (List *) restriction_clauses);
  304. /*
  305.  * The index must have an ordering for the path to have (ordering)
  306.  * keys, and vice versa.
  307.  */
  308. if (pathnode->path.pathorder->ord.sortop)
  309. {
  310. pathnode->path.pathkeys = collect_index_pathkeys(index->indexkeys,
  311.  rel->targetlist);
  312. /*
  313.  * Check that the keys haven't 'disappeared', since they may no
  314.  * longer be in the target list (i.e., index keys that are not
  315.  * relevant to the scan are not applied to the scan path node, so
  316.  * if no index keys were found, we can't order the path).
  317.  */
  318. if (pathnode->path.pathkeys == NULL)
  319. pathnode->path.pathorder->ord.sortop = NULL;
  320. }
  321. else
  322. pathnode->path.pathkeys = NULL;
  323. if (is_join_scan || restriction_clauses == NULL)
  324. {
  325. /*
  326.  * Indices used for joins or sorting result nodes don't restrict
  327.  * the result at all, they simply order it, so compute the scan
  328.  * cost accordingly -- use a selectivity of 1.0.
  329.  */
  330. /* is the statement above really true? what about IndexScan as the
  331.    inner of a join? */
  332. pathnode->path.path_cost = cost_index(lfirsti(index->relids),
  333.   index->pages,
  334.   1.0,
  335.   rel->pages,
  336.   rel->tuples,
  337.   index->pages,
  338.   index->tuples,
  339.   false);
  340. #ifdef NOT_USED
  341. /* add in expensive functions cost!  -- JMH, 7/7/92 */
  342. if (XfuncMode != XFUNC_OFF)
  343. {
  344. pathnode->path_cost = (pathnode->path_cost +
  345.  xfunc_get_path_cost((Path *) pathnode));
  346. }
  347. #endif
  348. }
  349. else
  350. {
  351. /*
  352.  * Compute scan cost for the case when 'index' is used with a
  353.  * restriction clause.
  354.  */
  355. List    *attnos;
  356. List    *values;
  357. List    *flags;
  358. float npages;
  359. float selec;
  360. Cost clausesel;
  361. get_relattvals(restriction_clauses,
  362.    &attnos,
  363.    &values,
  364.    &flags);
  365. index_selectivity(lfirsti(index->relids),
  366.   index->classlist,
  367.   get_opnos(restriction_clauses),
  368.   getrelid(lfirsti(rel->relids),
  369.    root->rtable),
  370.   attnos,
  371.   values,
  372.   flags,
  373.   length(restriction_clauses),
  374.   &npages,
  375.   &selec);
  376. /* each clause gets an equal selectivity */
  377. clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
  378. pathnode->indexqual = restriction_clauses;
  379. pathnode->path.path_cost = cost_index(lfirsti(index->relids),
  380.   (int) npages,
  381.   selec,
  382.   rel->pages,
  383.   rel->tuples,
  384.   index->pages,
  385.   index->tuples,
  386.   false);
  387. #ifdef NOT_USED
  388. /* add in expensive functions cost!  -- JMH, 7/7/92 */
  389. if (XfuncMode != XFUNC_OFF)
  390. pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
  391. #endif
  392. /*
  393.  * Set selectivities of clauses used with index to the selectivity
  394.  * of this index, subdividing the selectivity equally over each of
  395.  * the clauses.
  396.  */
  397. /* XXX Can this divide the selectivities in a better way? */
  398. set_clause_selectivities(restriction_clauses, clausesel);
  399. }
  400. return pathnode;
  401. }
  402. /*
  403.  * create_nestloop_path
  404.  *   Creates a pathnode corresponding to a nestloop join between two
  405.  *   relations.
  406.  *
  407.  * 'joinrel' is the join relation.
  408.  * 'outer_rel' is the outer join relation
  409.  * 'outer_path' is the outer join path.
  410.  * 'inner_path' is the inner join path.
  411.  * 'pathkeys' are the keys of the path
  412.  *
  413.  * Returns the resulting path node.
  414.  *
  415.  */
  416. NestPath   *
  417. create_nestloop_path(RelOptInfo *joinrel,
  418.  RelOptInfo *outer_rel,
  419.  Path *outer_path,
  420.  Path *inner_path,
  421.  List *pathkeys)
  422. {
  423. NestPath   *pathnode = makeNode(NestPath);
  424. pathnode->path.pathtype = T_NestLoop;
  425. pathnode->path.parent = joinrel;
  426. pathnode->outerjoinpath = outer_path;
  427. pathnode->innerjoinpath = inner_path;
  428. pathnode->pathinfo = joinrel->restrictinfo;
  429. pathnode->path.pathkeys = pathkeys;
  430. pathnode->path.joinid = NIL;
  431. pathnode->path.outerjoincost = (Cost) 0.0;
  432. pathnode->path.loc_restrictinfo = NIL;
  433. pathnode->path.pathorder = makeNode(PathOrder);
  434. if (pathkeys)
  435. {
  436. pathnode->path.pathorder->ordtype = outer_path->pathorder->ordtype;
  437. if (outer_path->pathorder->ordtype == SORTOP_ORDER)
  438. pathnode->path.pathorder->ord.sortop = outer_path->pathorder->ord.sortop;
  439. else
  440. pathnode->path.pathorder->ord.merge = outer_path->pathorder->ord.merge;
  441. }
  442. else
  443. {
  444. pathnode->path.pathorder->ordtype = SORTOP_ORDER;
  445. pathnode->path.pathorder->ord.sortop = NULL;
  446. }
  447. pathnode->path.path_cost = cost_nestloop(outer_path->path_cost,
  448.  inner_path->path_cost,
  449.  outer_rel->size,
  450.  inner_path->parent->size,
  451.  page_size(outer_rel->size,
  452.    outer_rel->width),
  453.  IsA(inner_path, IndexPath));
  454. /* add in expensive function costs -- JMH 7/7/92 */
  455. #ifdef NOT_USED
  456. if (XfuncMode != XFUNC_OFF)
  457. pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
  458. #endif
  459. return pathnode;
  460. }
  461. /*
  462.  * create_mergejoin_path
  463.  *   Creates a pathnode corresponding to a mergejoin join between
  464.  *   two relations
  465.  *
  466.  * 'joinrel' is the join relation
  467.  * 'outersize' is the number of tuples in the outer relation
  468.  * 'innersize' is the number of tuples in the inner relation
  469.  * 'outerwidth' is the number of bytes per tuple in the outer relation
  470.  * 'innerwidth' is the number of bytes per tuple in the inner relation
  471.  * 'outer_path' is the outer path
  472.  * 'inner_path' is the inner path
  473.  * 'pathkeys' are the new keys of the join relation
  474.  * 'order' is the sort order required for the merge
  475.  * 'mergeclauses' are the applicable join/restriction clauses
  476.  * 'outersortkeys' are the sort varkeys for the outer relation
  477.  * 'innersortkeys' are the sort varkeys for the inner relation
  478.  *
  479.  */
  480. MergePath  *
  481. create_mergejoin_path(RelOptInfo *joinrel,
  482.   int outersize,
  483.   int innersize,
  484.   int outerwidth,
  485.   int innerwidth,
  486.   Path *outer_path,
  487.   Path *inner_path,
  488.   List *pathkeys,
  489.   MergeOrder *order,
  490.   List *mergeclauses,
  491.   List *outersortkeys,
  492.   List *innersortkeys)
  493. {
  494. MergePath  *pathnode = makeNode(MergePath);
  495. pathnode->jpath.path.pathtype = T_MergeJoin;
  496. pathnode->jpath.path.parent = joinrel;
  497. pathnode->jpath.outerjoinpath = outer_path;
  498. pathnode->jpath.innerjoinpath = inner_path;
  499. pathnode->jpath.pathinfo = joinrel->restrictinfo;
  500. pathnode->jpath.path.pathkeys = pathkeys;
  501. pathnode->jpath.path.pathorder = makeNode(PathOrder);
  502. pathnode->jpath.path.pathorder->ordtype = MERGE_ORDER;
  503. pathnode->jpath.path.pathorder->ord.merge = order;
  504. pathnode->path_mergeclauses = mergeclauses;
  505. pathnode->jpath.path.loc_restrictinfo = NIL;
  506. pathnode->outersortkeys = outersortkeys;
  507. pathnode->innersortkeys = innersortkeys;
  508. pathnode->jpath.path.path_cost = cost_mergejoin(outer_path->path_cost,
  509. inner_path->path_cost,
  510. outersortkeys,
  511. innersortkeys,
  512. outersize,
  513. innersize,
  514. outerwidth,
  515. innerwidth);
  516. /* add in expensive function costs -- JMH 7/7/92 */
  517. #ifdef NOT_USED
  518. if (XfuncMode != XFUNC_OFF)
  519. pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
  520. #endif
  521. return pathnode;
  522. }
  523. /*
  524.  * create_hashjoin_path-- XXX HASH
  525.  *   Creates a pathnode corresponding to a hash join between two relations.
  526.  *
  527.  * 'joinrel' is the join relation
  528.  * 'outersize' is the number of tuples in the outer relation
  529.  * 'innersize' is the number of tuples in the inner relation
  530.  * 'outerwidth' is the number of bytes per tuple in the outer relation
  531.  * 'innerwidth' is the number of bytes per tuple in the inner relation
  532.  * 'outer_path' is the outer path
  533.  * 'inner_path' is the inner path
  534.  * 'pathkeys' are the new keys of the join relation
  535.  * 'operator' is the hashjoin operator
  536.  * 'hashclauses' are the applicable join/restriction clauses
  537.  * 'outerkeys' are the sort varkeys for the outer relation
  538.  * 'innerkeys' are the sort varkeys for the inner relation
  539.  *
  540.  */
  541. HashPath   *
  542. create_hashjoin_path(RelOptInfo *joinrel,
  543.  int outersize,
  544.  int innersize,
  545.  int outerwidth,
  546.  int innerwidth,
  547.  Path *outer_path,
  548.  Path *inner_path,
  549.  List *pathkeys,
  550.  Oid operator,
  551.  List *hashclauses,
  552.  List *outerkeys,
  553.  List *innerkeys)
  554. {
  555. HashPath   *pathnode = makeNode(HashPath);
  556. pathnode->jpath.path.pathtype = T_HashJoin;
  557. pathnode->jpath.path.parent = joinrel;
  558. pathnode->jpath.outerjoinpath = outer_path;
  559. pathnode->jpath.innerjoinpath = inner_path;
  560. pathnode->jpath.pathinfo = joinrel->restrictinfo;
  561. pathnode->jpath.path.loc_restrictinfo = NIL;
  562. pathnode->jpath.path.pathkeys = pathkeys;
  563. pathnode->jpath.path.pathorder = makeNode(PathOrder);
  564. pathnode->jpath.path.pathorder->ordtype = SORTOP_ORDER;
  565. pathnode->jpath.path.pathorder->ord.sortop = NULL;
  566. pathnode->jpath.path.outerjoincost = (Cost) 0.0;
  567. pathnode->jpath.path.joinid = (Relids) NULL;
  568. /* pathnode->hashjoinoperator = operator;  */
  569. pathnode->path_hashclauses = hashclauses;
  570. pathnode->outerhashkeys = outerkeys;
  571. pathnode->innerhashkeys = innerkeys;
  572. pathnode->jpath.path.path_cost = cost_hashjoin(outer_path->path_cost,
  573.    inner_path->path_cost,
  574.    outerkeys,
  575.    innerkeys,
  576.    outersize, innersize,
  577.  outerwidth, innerwidth);
  578. /* add in expensive function costs -- JMH 7/7/92 */
  579. #ifdef NOT_USED
  580. if (XfuncMode != XFUNC_OFF)
  581. pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
  582. #endif
  583. return pathnode;
  584. }