The problem is that the function arguments are not considered as possible key
candidates for index scan and so only a sequential scan is possible inside
the body of a function.  I have therefore made some patches to the optimizer
so that indices are now used also by functions.  I have also moved the plan
debug message from pg_eval to pg_plan so that it is printed also for plans
genereated for function execution.  I had also to add an index rescan to the
executor because it ignored the parameters set in the execution state, they
were flagged as runtime variables in ExecInitIndexScan but then never used
by the executor so that the scan were always done with any key=1. Very odd.
This means that an index rescan is now done twice for each function execution
which uses an index, the first time when the index scan is initialized and
the second when the actual function arguments are finally available for the
execution.  I don't know what is the cost of an double index scan but I
suppose it is anyway less than the cost of a full sequential scan, at leat
for large tables. This is my patch, you must also add -DINDEXSCAN_PATCH in
Makefile.global to enable the changes.

Submitted by: Massimo Dal Zotto <dz@cs.unitn.it>
This commit is contained in:
Marc G. Fournier 1996-09-10 06:48:52 +00:00
parent f2f53aee0f
commit 796f78998e
5 changed files with 58 additions and 6 deletions

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.2 1996/07/30 07:45:27 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.3 1996/09/10 06:48:01 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -145,6 +145,20 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
dest = queryDesc->dest;
destination = (void (*)()) DestToFunction(dest);
#ifdef INDEXSCAN_PATCH
/*
* If the plan is an index scan and some of the scan key are
* function arguments rescan the indices after the parameter
* values have been stored in the execution state. DZ - 27-8-1996
*/
if ((nodeTag(plan) == T_IndexScan) &&
(((IndexScan *)plan)->indxstate->iss_RuntimeKeyInfo != NULL)) {
ExprContext *econtext;
econtext = ((IndexScan *)plan)->scan.scanstate->cstate.cs_ExprContext;
ExecIndexReScan((IndexScan *)plan, econtext, plan);
}
#endif
switch(feature) {
case EXEC_RUN:

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.2 1996/07/19 07:13:26 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.3 1996/09/10 06:48:12 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -493,7 +493,13 @@ match_clause_to_indexkey(Rel *rel,
/*
* Check for standard s-argable clause
*/
#ifdef INDEXSCAN_PATCH
/* Handle also function parameters. DZ - 27-8-1996 */
if ((rightop && IsA(rightop,Const)) ||
(rightop && IsA(rightop,Param)))
#else
if (rightop && IsA(rightop,Const))
#endif
{
restrict_op = ((Oper*)((Expr*)clause)->oper)->opno;
isIndexable =

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.2 1996/08/26 06:31:15 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.3 1996/09/10 06:48:32 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -626,6 +626,11 @@ fix_indxqual_references(Node *clause, Path *index_path)
}
} else if(IsA(clause,Const)) {
return(clause);
#ifdef INDEXSCAN_PATCH
} else if(IsA(clause,Param)) {
/* Function parameter used as index scan arg. DZ - 27-8-1996 */
return(clause);
#endif
} else if(is_opclause(clause) &&
is_funcclause((Node*)get_leftop((Expr*)clause)) &&
((Func*)((Expr*)get_leftop((Expr*)clause))->oper)->funcisindex){

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.2 1996/07/25 20:36:46 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.3 1996/09/10 06:48:41 scrappy Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -595,6 +595,14 @@ get_relattval(Node *clause,
*flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_NOT_CONSTANT_);
}
#ifdef INDEXSCAN_PATCH
} else if (is_opclause(clause) && IsA(left,Var) && IsA(right,Param)) {
/* Function parameter used as index scan arg. DZ - 27-8-1996 */
*relid = left->varno;
*attno = left->varattno;
*constval = 0;
*flag = (_SELEC_NOT_CONSTANT_);
#endif
}else if (is_opclause(clause) &&
is_funcclause((Node*)left) &&
IsA(right,Const)) {

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.6 1996/08/19 13:37:49 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.7 1996/09/10 06:48:52 scrappy Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -533,6 +533,19 @@ pg_plan(char *query_string, /* string to execute */
ShowUsage();
}
plan_list = lappend(plan_list, plan);
#ifdef INDEXSCAN_PATCH
/* ----------------
* Print plan if debugging.
* This has been moved here to get debugging output
* also for queries in functions. DZ - 27-8-1996
* ----------------
*/
if ( DebugPrintPlan == true ) {
printf("\nPlan is :\n");
nodeDisplay(plan);
printf("\n");
}
#endif
}
}
@ -607,6 +620,11 @@ pg_eval_dest(char *query_string, /* string to execute */
plan = (Plan *) lfirst(plan_list);
plan_list = lnext(plan_list);
#ifdef INDEXSCAN_PATCH
/*
* Print moved in pg_plan. DZ - 27-8-1996
*/
#else
/* ----------------
* print plan if debugging
* ----------------
@ -616,6 +634,7 @@ pg_eval_dest(char *query_string, /* string to execute */
nodeDisplay(plan);
printf("\n");
}
#endif
/* ----------------
* execute the plan
@ -1227,7 +1246,7 @@ PostgresMain(int argc, char *argv[])
*/
if (IsUnderPostmaster == false) {
puts("\nPOSTGRES backend interactive interface");
puts("$Revision: 1.6 $ $Date: 1996/08/19 13:37:49 $");
puts("$Revision: 1.7 $ $Date: 1996/09/10 06:48:52 $");
}
/* ----------------