Sql 存储过程的Oracle性能调优

Sql 存储过程的Oracle性能调优,sql,oracle,plsql,Sql,Oracle,Plsql,最近遇到的一个场景中,我有很多select语句,如下所示: 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是存储过程的输入,我需要优化查询。是否有任何方法可以检查v_param1、v_param1是否为空,则无需在或之前检

最近遇到的一个场景中,我有很多select语句,如下所示:

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
是存储过程的输入,我需要优化查询。是否有任何方法可以检查v_param1、v_param1是否为空,则无需在或之前检查第一个条件。

删除该或并按如下方式更改条件

和upper(表1.col1)类似于upper(v_param1)| |'% 和upper(表2.col2)类似于upper(v_param2)| |'%


注意:如果param value为null,则它将执行类似“upper(col1)like“%”这样的条件。

您可以做的最简单的事情是切换条件求值的顺序:

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不保证会使OR计算短路,但以空测试为先导会让它朝着正确的方向前进

如果使用存储过程,则可以在pl/sql中动态构造查询,绑定变量并使用dbms\U 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);
...
尝试使用:

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

您可以做的一件事是根据第1列和第2列的上限为响应创建一个基于函数的索引,这不符合我的要求,因为有很多选择with and子句,在这些选择with and子句上创建索引会降低其他服务对这些表执行insert或update操作的性能。您不能以大写形式存储Table1.col1和Table1.col2吗。这将避免在查询期间将它们转换为大写的过载。