diff options
author | Bruce Momjian <bruce@momjian.us> | 1999-11-23 20:07:06 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1999-11-23 20:07:06 +0000 |
commit | 6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0 (patch) | |
tree | 797395e647f1e8a741214d5eaafb9ee66a64c462 /src/backend/optimizer/path | |
parent | 54ffd4677aaf56e928af9e3f689297d6c06d1fe9 (diff) | |
download | postgresql-6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0.tar.gz postgresql-6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0.zip |
Tid access method feature from Hiroshi Inoue, Inoue@tpf.co.jp
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/Makefile | 5 | ||||
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 9 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 26 | ||||
-rw-r--r-- | src/backend/optimizer/path/tidpath.c | 296 |
4 files changed, 331 insertions, 5 deletions
diff --git a/src/backend/optimizer/path/Makefile b/src/backend/optimizer/path/Makefile index cdc401b8310..5e903ce666d 100644 --- a/src/backend/optimizer/path/Makefile +++ b/src/backend/optimizer/path/Makefile @@ -4,7 +4,7 @@ # Makefile for optimizer/path # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/optimizer/path/Makefile,v 1.9 1999/08/16 02:17:50 tgl Exp $ +# $Header: /cvsroot/pgsql/src/backend/optimizer/path/Makefile,v 1.10 1999/11/23 20:06:54 momjian Exp $ # #------------------------------------------------------------------------- @@ -14,7 +14,8 @@ include ../../../Makefile.global CFLAGS += -I../.. OBJS = allpaths.o clausesel.o costsize.o indxpath.o \ - joinpath.o joinrels.o orindxpath.o pathkeys.o prune.o + joinpath.o joinrels.o orindxpath.o pathkeys.o prune.o \ + tidpath.o all: SUBSYS.o diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 23c759bd6e6..3cc8466f77b 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.53 1999/08/16 02:17:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.54 1999/11/23 20:06:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -108,9 +108,14 @@ set_base_rel_pathlist(Query *root, List *rels) List *sequential_scan_list; List *rel_index_scan_list; List *or_index_scan_list; + List *tidscan_pathlist; sequential_scan_list = lcons(create_seqscan_path(rel), NIL); - + /* Tid Scan Pathlist add */ + tidscan_pathlist = create_tidscan_paths(root, rel); + if (tidscan_pathlist) + sequential_scan_list = nconc(sequential_scan_list, + tidscan_pathlist); rel_index_scan_list = create_index_paths(root, rel, indices, diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index fcf462b83eb..99ee42cf8c7 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -18,7 +18,7 @@ * Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.45 1999/08/22 20:14:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.46 1999/11/23 20:06:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -59,6 +59,7 @@ bool _enable_sort_ = true; bool _enable_nestloop_ = true; bool _enable_mergejoin_ = true; bool _enable_hashjoin_ = true; +bool _enable_tidscan_ = true; Cost _cpu_page_weight_ = _CPU_PAGE_WEIGHT_; Cost _cpu_index_page_weight_ = _CPU_INDEX_PAGE_WEIGHT_; @@ -175,6 +176,29 @@ cost_index(Oid indexid, } /* + * cost_tidscan + * Determines and returns the cost of scanning a relation using tid-s. + * + * disk = number of tids + * cpu = *CPU-PAGE-WEIGHT* * number_of_tids + * + * Returns a flonum. + * + */ +Cost +cost_tidscan(List *tideval) +{ + Cost temp = 0; + + if (!_enable_tidscan_) + temp += _disable_cost_; + + temp += (1.0 + _cpu_page_weight_) * length(tideval); + + return temp; +} + +/* * cost_sort * Determines and returns the cost of sorting a relation by considering * the cost of doing an external sort: XXX this is probably too low diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c new file mode 100644 index 00000000000..9e618f7a872 --- /dev/null +++ b/src/backend/optimizer/path/tidpath.c @@ -0,0 +1,296 @@ +/*------------------------------------------------------------------------- + * + * tidpath.c + * Routines to determine which tids are usable for scanning a + * given relation, and create TidPaths accordingly. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.1 1999/11/23 20:06:55 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#include <math.h> + +#include "postgres.h" + +#include "access/heapam.h" +#include "catalog/catname.h" +#include "catalog/pg_amop.h" +#include "catalog/pg_operator.h" +#include "executor/executor.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/clauses.h" +#include "optimizer/cost.h" +#include "optimizer/pathnode.h" +#include "optimizer/paths.h" +#include "optimizer/plancat.h" +#include "optimizer/restrictinfo.h" +#include "parser/parse_coerce.h" +#include "parser/parse_expr.h" +#include "parser/parse_oper.h" +#include "parser/parsetree.h" +#include "utils/lsyscache.h" + +static List *create_tidscan_joinpaths(RelOptInfo *); +static List *TidqualFromRestrictinfo(List *relids, List * restrictinfo); +static bool isEvaluable(int varno, Node *node); +static Node *TidequalClause(int varno, Expr *node); +static List *TidqualFromExpr(int varno, Expr *expr); + +static +bool isEvaluable(int varno, Node *node) +{ + List *lst; + Expr *expr; + + if (IsA(node, Const)) return true; + if (IsA(node, Param)) return true; + if (IsA(node, Var)) + { + Var *var = (Var *)node; + + if (var->varno == varno) + return false; + return true; + } + if (!is_funcclause(node)) return false; + expr = (Expr *)node; + foreach (lst, expr->args) + { + if (!isEvaluable(varno, lfirst(lst))) + return false; + } + + return true; +} + +/* + * The 2nd parameter should be an opclause + * Extract the right node if the opclause is CTID= .... + * or the left node if the opclause is ....=CTID + */ +static +Node *TidequalClause(int varno, Expr *node) +{ + Node *rnode = 0, *arg1, *arg2, *arg; + Oper *oper; + Var *var; + Const *aconst; + Param *param; + Expr *expr; + + if (!node->oper) return rnode; + if (!node->args) return rnode; + if (length(node->args) != 2) return rnode; + oper = (Oper *) node->oper; + if (oper->opno != TIDEqualOperator) + return rnode; + arg1 = lfirst(node->args); + arg2 = lsecond(node->args); + + arg = (Node *)0; + if (IsA(arg1, Var)) + { + var = (Var *) arg1; + if (var->varno == varno && + var->varattno == SelfItemPointerAttributeNumber && + var->vartype == TIDOID) + arg = arg2; + else if (var->varnoold == varno && + var->varoattno == SelfItemPointerAttributeNumber && + var->vartype == TIDOID) + arg = arg2; + } + if ((!arg) && IsA(arg2, Var)) + { + var = (Var *) arg2; + if (var->varno == varno && + var->varattno == SelfItemPointerAttributeNumber && + var->vartype == TIDOID) + arg = arg1; + } + if (!arg) + return rnode; + switch (nodeTag(arg)) + { + case T_Const: + aconst = (Const *) arg; + if (aconst->consttype != TIDOID) + return rnode; + if (aconst->constbyval) + return rnode; + rnode = arg; + break; + case T_Param: + param = (Param *) arg; + if (param->paramtype != TIDOID) + return rnode; + rnode = arg; + break; + case T_Var: + var = (Var *) arg; + if (var->varno == varno || + var->vartype != TIDOID) + return rnode; + rnode = arg; + break; + case T_Expr: + expr = (Expr *) arg; + if (expr->typeOid != TIDOID) return rnode; + if (expr->opType != FUNC_EXPR) return rnode; + if (isEvaluable(varno, (Node *)expr)) + rnode = arg; + break; + default: + break; + } + return rnode; +} + +/* + * Extract the list of CTID values from a specified expr node. + * When the expr node is an or_clause,we try to extract CTID + * values from all member nodes. However we would discard them + * all if we couldn't extract CTID values from a member node. + * When the expr node is an and_clause,we return the list of + * CTID values if we could extract the CTID values from a member + * node. + */ +static +List *TidqualFromExpr(int varno, Expr *expr) +{ + List *rlst = NIL, *lst, *frtn; + Node *node = (Node *) expr, *rnode; + + if (is_opclause(node)) + { + rnode = TidequalClause(varno, expr); + if (rnode) + { + rlst = lcons(rnode, rlst); + } + } + else if (and_clause(node)) + { + foreach (lst, expr->args) + { + node = lfirst(lst); + if (!IsA(node, Expr)) + continue; + rlst = TidqualFromExpr(varno, (Expr *)node); + if (rlst) + break; + } + } + else if (or_clause(node)) + { + foreach (lst, expr->args) + { + node = lfirst(lst); + if (IsA(node, Expr) && + (frtn = TidqualFromExpr(varno, (Expr *)node)) ) + { + rlst = nconc(rlst, frtn); + } + else + { + if (rlst) + freeList(rlst); + rlst = NIL; + break; + } + } + } + return rlst; +} + +static +List *TidqualFromRestrictinfo(List *relids, List * restrictinfo) +{ + List *lst, *rlst = NIL; + int varno; + Node *node; + Expr *expr; + + if (length(relids)>1) return NIL; + varno = (int)lfirst(relids); + foreach (lst, restrictinfo) + { + node = lfirst(lst); + if (!IsA(node, RestrictInfo)) continue; + expr = ((RestrictInfo *)node)->clause; + rlst = TidqualFromExpr(varno, expr); + if (rlst) + { + break; + } + } + return rlst; +} + +/* + * create_tidscan_joinpaths + * Creates a path corresponding to a tid_direct scan, returning the + * pathnode. + * + */ +List * +create_tidscan_joinpaths(RelOptInfo *rel) +{ + List *rlst = NIL, *lst; + TidPath *pathnode = (TidPath *)0; + List *restinfo, *tideval; + + foreach (lst, rel->joininfo) + { + JoinInfo *joininfo = (JoinInfo *)lfirst(lst); + restinfo = joininfo->jinfo_restrictinfo; + tideval = TidqualFromRestrictinfo(rel->relids, restinfo); + if (tideval && length(tideval) == 1) + { + pathnode = makeNode(TidPath); + + pathnode->path.pathtype = T_TidScan; + pathnode->path.parent = rel; + pathnode->path.path_cost = 0.0; + pathnode->path.pathkeys = NIL; + + pathnode->path.path_cost = cost_tidscan(tideval); + pathnode->tideval = tideval; + /* + pathnode->tideval = copyObject(tideval); + freeList(tideval); + */ + pathnode->unjoined_relids = joininfo->unjoined_relids; + rlst = lappend(rlst, pathnode); + } + } + rel->innerjoin = nconc(rel->innerjoin, rlst); + return rlst; +} + +/* + * create_tidscan_paths + * Creates a path corresponding to a tid direct scan, returning the + * pathnode List. + * + */ +List * +create_tidscan_paths(Query *root, RelOptInfo *rel) +{ + List *rlst = NIL; + TidPath *pathnode = (TidPath *)0; + List *tideval = TidqualFromRestrictinfo(rel->relids, rel->restrictinfo); + + if (tideval) + pathnode = create_tidscan_path(rel, tideval); + if (pathnode) + rlst = lcons(pathnode, rlst); + create_tidscan_joinpaths(rel); + + return rlst; +} |