On Tuesday, May 7, 2013 5:35:03 PM UTC-7, Fin wrote:
> Using DB2 Express-C 10.1.2 LUW on Win 7 Pro SP1 both 64-Bit, I have
> the below listed example portion of a SP.
> The INSERT statement using the variable V_ACT_DATE that is input at
> the time of the call statement ie: CALL TEMP_PROC('05/07/2013');
> The problem appears to some form of DATE conversion, as if I hard
> code the date by replacing V_ACT_DATE in the select statement with
> the actual date ie: '05/07/2013' all is fine. However if I use the
> variable name in it's place ie: V_ACT_DATE (as written in the code)
> then all hell breaks loose. The SP finishes successfully, but
> instead of taking 10 secs to run, it takes 7 minutes and hammers the
> hell out of my SSD in the TMPDB2ADMIN table space writing over 50gb
> of temp data to insert some 350k records.
I suspect the issue is that when you hard code the date into the
stored procedure, DB2 is able to use distribution statistics (assuming
you've collected them in your RUNSTATS) to choose the query plan, and
the dates you typically run with provide have very low selectivity.
With this knowledge, the optimizer chooses a very effective access
plan when it knows the value of V_ACT_DATE.
However, when you use the variable, the optimizer does not know what
the value of the variable will be at runtime, so it makes an
assumption about how much data will qualify, and then builds the
access plan based on that assumption. If the assumption is wrong
(meaning it thinks a LOT more data will qualify than actually does),
then the access plan may be very inefficient (as you've found).
Because your INSERT statement is a static statement (i.e. it's
compiled when the procedure is created), the best way to resolve this
is to set the REOPT ONCE or REOPT ALWAYS options. These tell DB2 to
recompile the access plan with the actual value of any parameters at
runtime.
You can do this either by rebinding the existing stored procedure
(using the REBIND_ROUTINE_PACKAGE stored procedure with the
appropriate REOPT option), or you can call the stored procedure
SYSPROC.SET_ROUTINE_OPTS('REOPT ONCE') and then recreate your stored
procedure.