On Mon, 2007-11-26 at 09:55 -0500, Tom Lane wrote:
> Simon Riggs <[EMAIL PROTECTED]> writes:
> > But I think there must be an action that we can take for 8.3 and that
> > much runtime should not be given away easily. ISTM that we can win back
> > the losses Guillaume has identified, plus gain a little more even.
> 
> Perhaps some sanity could be restored to this discussion by pointing out
> that the 2007-01-01 code *also* clocks in at 37% spent in
> oper_select_candidate.  IOW it's been like this for a very long time.

[I'm replying to the wrong message, I know.]

Here's where I am:

Basic test was to replace call to oper_select_candidate with a single
item that was fed by a hardcoded value for varchar equality operator.
This is the oper_cache.v1.patch enclosed; the 5 line patch.

Test results were
- w/o patch     ~10,500 tps with pgbench_varchar.sql
- with patch    ~15,500 tps with pgbench_varchar.sql (**big gain**)
- w/o patch     ~16,250 tps with pgbench_integer.sql
- with patch    ~16,250 tps with pgbench_integer.sql

Tables are standard pgbench, varchar test table created using:
create table av as select aid::varchar, bid, abalance, filler from
accounts;
create unique index av_pkey on av (aid);

The impact of calling oper_select_candidate() is big enough that it will
affect any query that is read only and has 1 or 2 predicates when at
least one of them is a VARCHAR_col = const query.

What I'm actually proposing is a patch implementing a oper_select_hook
function pointer, which allows the user to do anything they want. I'm
just re-writing that as a plugin now, but the backend patch is included
here for discussion. oper_select_hook.v1.patch

-- 
  Simon Riggs
  2ndQuadrant  http://www.2ndQuadrant.com
Index: src/backend/parser/parse_oper.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/parser/parse_oper.c,v
retrieving revision 1.98
diff -c -r1.98 parse_oper.c
*** src/backend/parser/parse_oper.c	22 Nov 2007 19:40:25 -0000	1.98
--- src/backend/parser/parse_oper.c	26 Nov 2007 16:28:42 -0000
***************
*** 28,33 ****
--- 28,34 ----
  #include "utils/syscache.h"
  #include "utils/typcache.h"
  
+ static Oid operOidCache = InvalidOid;
  
  static Oid	binary_oper_exact(List *opname, Oid arg1, Oid arg2);
  static FuncDetailCode oper_select_candidate(int nargs,
***************
*** 516,534 ****
  		/* No operators found? Then fail... */
  		if (clist != NULL)
  		{
! 			/*
! 			 * Unspecified type for one of the arguments? then use the other
! 			 * (XXX this is probably dead code?)
! 			 */
! 			Oid			inputOids[2];
  
! 			if (rtypeId == InvalidOid)
! 				rtypeId = ltypeId;
! 			else if (ltypeId == InvalidOid)
! 				ltypeId = rtypeId;
! 			inputOids[0] = ltypeId;
! 			inputOids[1] = rtypeId;
! 			fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
  		}
  	}
  
--- 517,543 ----
  		/* No operators found? Then fail... */
  		if (clist != NULL)
  		{
! 			if (OidIsValid(operOidCache))
! 				operOid = operOidCache;
! 			else
! 			{
! 				/*
! 				 * Unspecified type for one of the arguments? then use the other
! 				 * (XXX this is probably dead code?)
! 				 */
! 				Oid			inputOids[2];
! 
! 				if (rtypeId == InvalidOid)
! 					rtypeId = ltypeId;
! 				else if (ltypeId == InvalidOid)
! 					ltypeId = rtypeId;
! 				inputOids[0] = ltypeId;
! 				inputOids[1] = rtypeId;
! 				fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
  
! 				if (ltypeId == 1043 && rtypeId == 705)
! 					operOidCache = operOid;
! 			}
  		}
  	}
  
\set naccounts 100000 * :scale
\setrandom aid 1 :naccounts
SELECT abalance FROM accounts WHERE aid = :aid;

\set naccounts 100000 * :scale
\setrandom aid 1 :naccounts
SELECT abalance FROM av WHERE aid = ':aid';

Index: src/backend/parser/parse_oper.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/parser/parse_oper.c,v
retrieving revision 1.98
diff -c -r1.98 parse_oper.c
*** src/backend/parser/parse_oper.c	22 Nov 2007 19:40:25 -0000	1.98
--- src/backend/parser/parse_oper.c	26 Nov 2007 23:08:09 -0000
***************
*** 28,33 ****
--- 28,34 ----
  #include "utils/syscache.h"
  #include "utils/typcache.h"
  
+ oper_select_hook_type oper_select_hook = NULL;
  
  static Oid	binary_oper_exact(List *opname, Oid arg1, Oid arg2);
  static FuncDetailCode oper_select_candidate(int nargs,
***************
*** 528,534 ****
  				ltypeId = rtypeId;
  			inputOids[0] = ltypeId;
  			inputOids[1] = rtypeId;
! 			fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
  		}
  	}
  
--- 529,544 ----
  				ltypeId = rtypeId;
  			inputOids[0] = ltypeId;
  			inputOids[1] = rtypeId;
! 
! 			/*
! 			 * Allow user defined operator selection, allowing hard-coding
! 			 * cacheing or other mechanisms of operator selection for
! 			 * improved performance in certain circumstances
! 			 */
! 			if (oper_select_hook)
! 				fdresult = (* oper_select_hook) (2, inputOids, clist, &operOid);
! 			else
! 				fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
  		}
  	}
  
Index: src/include/parser/parse_oper.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/parser/parse_oper.h,v
retrieving revision 1.41
diff -c -r1.41 parse_oper.h
*** src/include/parser/parse_oper.h	5 Jan 2007 22:19:57 -0000	1.41
--- src/include/parser/parse_oper.h	26 Nov 2007 23:03:57 -0000
***************
*** 16,21 ****
--- 16,22 ----
  
  #include "access/htup.h"
  #include "parser/parse_node.h"
+ #include "parser/parse_func.h"
  
  
  typedef HeapTuple Operator;
***************
*** 37,42 ****
--- 38,49 ----
  extern Operator left_oper(ParseState *pstate, List *op, Oid arg,
  		  bool noError, int location);
  
+ typedef FuncDetailCode (*oper_select_hook_type) (int nargs,
+ 					  							  Oid *input_typeids,
+ 					  							  FuncCandidateList candidates,
+ 					  							  Oid *operOid);
+ extern PGDLLIMPORT oper_select_hook_type oper_select_hook;
+ 
  /* Routines to find operators that DO NOT require coercion --- ie, their */
  /* input types are either exactly as given, or binary-compatible */
  extern Operator compatible_oper(ParseState *pstate, List *op,
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend

Reply via email to