0

I have a select that return a single column, using as where clause 4 columns, and I created a specific index for this query. When I do this select using Dbeaver, the result return in 30~50 milliseconds.

      SELECT
       column1
      FROM 
       myTable
      WHERE
       column2 = a
       AND column3 = b
       AND (column4 = c AND column5 = d )
       FOR READ ONLY WITH UR; 

Now I created a procedure with this same simple select. The proc declare a P1, a 'cursor with return', do the select, open the cursor and close the P1. When I use the same dbeaver connection the result is returning between 1.2 ~ 1.6 seconds.

 CREATE  PROCEDURE myProc (
 IN a  DECIMAL(10),
 IN b  DECIMAL(10),
 IN c  DECIMAL(10),
 IN d  DECIMAL(10)
)
LANGUAGE SQL
DYNAMIC RESULT SETS 1
SPECIFIC myProc

P1: BEGIN

 DECLARE cursor1 CURSOR WITH RETURN for
 
  SELECT
   column1
  FROM 
   myTable
  WHERE
   column2 = a
   AND column3 = b
   AND (column4 = c AND column5 = d )
   FOR READ ONLY WITH UR; 
  
 OPEN cursor1;
END P1

Is this huge return difference correct? If wrong, Is there something wrong in my procedure that justifies this return time difference? Or could be something wrong in the DB configuration or the server that justifies this difference, something like few resources in the DB server or something like the proc not using the index( I don't know if procs in the DB2 use the index by default like the queries )?

I am new in DB2 and new in procedures creation. Thank you in advance.

Best regards, Luis

gomeslhlima
  • 141
  • 8
  • Apparently your select statement in dbeaver uses constants instead of parameter markers in the routine. Please, attach here both access plans (from the db2exfmt utility) - using constants as in dbeaver and question marks in place of the routine parameters (or an access plan from the explain_from_catalog routine). – Mark Barinstein Jan 03 '23 at 21:00
  • What platform and version of Db2? – Charles Jan 03 '23 at 21:14
  • I agree with Mark, Db2 cant make use of distribution statistics with parameter markers. You can try to rebind your procedure and see if that helps: CALL SYSPROC.REBIND_ROUTINE_PACKAGE ( 'P','','','MYPROC','REOPT ALWAYS'). If it does that is probably it. – Lennart - Slava Ukraini Jan 03 '23 at 22:53
  • @MarkBarinstein and others, Thank you for all comments. I solved( I don't know if is the best way ) the problem using a solution that I see for SQL Server. The solution is create local variables that will receive the parameters values, and use the variable in the queries, to guarantee always the best execution plan. I didn't knew if this was valid to DB2, but my proc now has almost the same response time compared to query. Worked! https://stackoverflow.com/questions/440944/sql-server-query-fast-but-slow-from-procedure?rq=1 – gomeslhlima Jan 06 '23 at 12:20

1 Answers1

0

I don't know if is the best way, but I solved the problem using a solution that I read for SQL Server. The solution is create local variables that will receive the parameters values, and use the variable in the queries, to guarantee always the best execution plan. I didn't knew if this was valid to DB2, but my proc now has almost the same response time compared to query. Worked!

Link of SQL Server post: SQL Server: Query fast, but slow from procedure

In this link above a user called @Jake give this explanation: "The reason this happens is because the procedures query plan is being cached, along with the parameters that were passed to it. On subsequent calls, this query plan generated will be reused with new parameters. This can cause problems because if the data is unevenly distributed, one parameter can generate a sub-optimal plan vs. another. Using local variables essentially does the same as OPTIMIZE FOR UNKNOWN because local variables cannot be sniffed."

I think that is the same for DB2, because worked. After I change these old procedures to use local variables my execution plan begun to use the indexes recently created

gomeslhlima
  • 141
  • 8
  • 2
    If you create an index after a routine creation, this index will not be used automatically by a static statement in the routine. You must either recreate the routine or rebind the routine package to make the optimizer consider this index use. – Mark Barinstein Jan 06 '23 at 13:14
  • @MarkBarinstein, even with this 'local variable solution' for not use plans cached I will need to recreate or rebind the routine always that I create a new index? Or this SQL Server workaround to force not use cached plans work also in DB2? – gomeslhlima Jan 06 '23 at 13:17
  • 1
    There is no difference between local variables and routine parameters use in a query in Db2. Index creation doesn't lead to automatic invalidation / recompilation of a static query plan. You must make the corresponding plan leave the package cache. You do it using rebinding routine package / recreating the routine to affect its static queries. – Mark Barinstein Jan 06 '23 at 14:27
  • @MarkBarinstein, I found a strategy that can work for my original purpose. Rebinding the proc with REOPT ALWAYS option( IBM DESC: The access path for a given SQL statement will always be compiled and re-optimized using the values of the host variables, parameter markers, global variables, or special registers known at each execution time. ). Do you know this approach? Is there any negative side effect in this approach? – gomeslhlima Jan 09 '23 at 12:56
  • 1
    There are pros and cons of using this option, of course. The negative effects are: 1) The statement controlled by this option is compiled every time and leaves the package cache immediately after the statement invocation - it's hard to monitor its performance, you may need, for example, an event monitor for package cache for this purpose, if you care about this. 2) your routine may contain other statements which don't need this option - you may use the corresponding optimizer guideline for some particular statement(s) instead. – Mark Barinstein Jan 09 '23 at 13:30