简体   繁体   English

针对存储过程的Oracle性能调优

[英]Oracle performance tuning for stored procedure

A scenario encountered recently where I have lots of select statements as: 最近遇到的场景中,我有很多选择语句,例如:

and  (UPPER(Table1.col1) LIKE UPPER(v_param1)||'%' or v_param1 is NULL)
and  (UPPER(Table2.col2) LIKE UPPER(v_param2)||'%' or v_param2 is NULL)

v_param1 & v_param2 are inputs to the stored procedure, I need to optimize the query. v_param1v_param2是存储过程的输入,我需要优化查询。 Is there any way to check if the v_param1,v_param1 are NULL then no need to check for the first condition before Or. 有什么方法可以检查v_param1,v_param1是否为NULL,然后无需在Or之前检查第一个条件。

Remove that or and change the condition like below 删除或更改如下条件

and upper(Table1.col1) like upper(v_param1)||'%' and upper(Table2.col2) like upper(v_param2)||'%' 和upper(Table1.col1)就像upper(v_param1)||'%',而upper(Table2.col2)就像upper(v_param2)||'%'

Note: if param value is null then it will execute the condition like "upper(col1) like '%'" 注意:如果param值为null,则它将执行类似于“ upper(col1)如'%'”的条件

The simplest thing you could do is to switch the order in which the conditions are evaluated: 您可以做的最简单的事情是切换评估条件的顺序:

and  (v_param1 is NULL or UPPER(Table1.col1) LIKE UPPER(v_param1)||'%'  )
and  (v_param2 is NULL or UPPER(Table2.col2) LIKE UPPER(v_param2)||'%'  )

Oracle does not guarantee to short-circuit the OR evaluation, but leading with the NULL test gives it a nudge in the right direction. Oracle不能保证短路OR评估,但是以NULL测试开头会使它朝正确的方向前进。

If you use stored procedure then you can construct your query dynamically in pl/sql, bind variables and execute query using dbms_sql. 如果使用存储过程,则可以在pl / sql中动态构造查询,绑定变量并使用dbms_sql执行查询。

...
  sSQL varchar2(32767) := 'select col1, col2 from Table1';
  iCurrId            number := DBMS_SQL.OPEN_CURSOR;
  iCurRes            number;
begin
  -- constant conditions
  sSQL := sSQL||' where col3 = :column3_value';

  -- add condition for v_param1 if it is not null  
  if v_param1 is not null then
    sSQL := sSQL||' and UPPER(Table1.col1) LIKE :v_param1_search_value';
  end if;

  -- add condition for v_param2 if it is not null  
  if v_param2 is not null then
    sSQL := sSQL||' and UPPER(Table1.col2) LIKE :v_param2_search_value';
  end if;

  -- parse cursor
  DBMS_SQL.PARSE(
    C             => iCurrId,
    STATEMENT     => sSQL,
    LANGUAGE_FLAG => DBMS_SQL.NATIVE
  );

  -- bind variables
  DBMS_SQL.BIND_VARIABLE( C => iCurrId, NAME => 'column3_value', VALUE => 'abcd');

  if v_param1 is not null then
    DBMS_SQL.BIND_VARIABLE( C => iCurrId, NAME => 'v_param1_search_value', VALUE => UPPER(v_param1)||'%');
  end if;

  if v_param2 is not null then
    DBMS_SQL.BIND_VARIABLE( C => iCurrId, NAME => 'v_param2_search_value', VALUE => UPPER(v_param2)||'%');
  end if;

  -- execute query
  iCurRes := DBMS_SQL.EXECUTE(iCurrId);
...

try to use: 尝试使用:

AND (
  CASE
    WHEN v_param2 IS NULL
    THEN NULL
    ELSE UPPER(Table2.col2)
  END LIKE UPPER(v_param2)
  ||'%'
OR v_param2      IS NULL)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM