【问题标题】:Oracle performance tuning for stored procedure存储过程的 Oracle 性能调优
【发布时间】:2018-12-20 03:45:42
【问题描述】:

最近遇到的一个场景,我有很多选择语句:

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 是否为NULL,那么就不需要在Or 之前检查第一个条件。

【问题讨论】:

  • 您可以做的一件事是在第 1 列和第 2 列的上部创建一个基于函数的索引
  • 感谢您的回复,这不符合我的要求,因为 and 子句有很多选择,并且在这些子句上创建索引会降低其他服务对这些表进行插入或更新的性能。跨度>
  • 您不能以大写形式存储 Table1.col1 和 Table1.col2。这将避免在查询期间将它们转换为大写的过载。

标签: sql oracle plsql


【解决方案1】:

尝试使用:

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

【讨论】:

    【解决方案2】:

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

    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 评估短路,但以 NULL 测试为先导可以使其朝着正确的方向轻推。

    【讨论】:

      【解决方案3】:

      如果您使用存储过程,那么您可以在 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);
      ...
      

      【讨论】:

        【解决方案4】:

        删除或更改条件,如下所示

        和upper(Table1.col1)一样upper(v_param1)||'%' 和upper(Table2.col2)之类的upper(v_param2)||'%'

        注意:如果参数值为空,那么它将执行类似“upper(col1) like '%'”的条件

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-15
          • 1970-01-01
          • 2012-02-26
          • 1970-01-01
          • 2016-06-25
          • 2019-03-09
          • 2013-03-17
          • 1970-01-01
          相关资源
          最近更新 更多