【问题标题】:Understanding 'BULK COLLECT' in Oracle Function了解 Oracle 函数中的“BULK COLLECT”
【发布时间】:2019-01-10 05:47:47
【问题描述】:

给定以下 Oracle 函数:

CREATE or REPLACE FUNCTION foo(id NUMBER, category VARCHAR) RETURN CHAR IS

TYPE MY_ARRAY2 IS TABLE OF NUMBER;
MY_ARRAY MY_ARRAY2;

BEGIN

   SELECT my_id BULK COLLECT INTO my_array FROM my_table

   RETURN (
            CASE WHEN category = 'FOO' AND (id member of MY_ARRAY)
              THEN 'Y'
              ELSE 'N'
            END
   );
END;

查找的性质是什么:

   SELECT my_id BULK COLLECT INTO my_array FROM my_table

或者,换一种说法,我可以在这一行或其他地方添加什么来加快查找速度 - 也许是一个索引?

【问题讨论】:

    标签: sql oracle performance plsql bulk-operations


    【解决方案1】:

    您所能做的就是使用带有MAXCOUNT 的单个选择

    AS
    ..
    ..
    
    v_retval VARCHAR2(10);
    
    
    SELECT MAX(CASE 
                WHEN category = 'FOO'
                    AND id = my_id 
                    THEN 'Y'
                ELSE 'N'
                END) INTO v_retval
    FROM my_table;
    RETURN v_retval;
    

    这依赖于字符串 "Y" > "N" 的事实。您也可以使用COUNT(CASE .. 和另一个案例where count > 1 THEN 'Y'

    在 id(或表中引用的其他列)上添加索引将有助于加快查询速度

    请注意,最好使用p_idp_category 形式的过程参数以避免冲突

    【讨论】:

    • 鉴于返回值是一个标量,这个响应比我的更相关:)
    • 谢谢!为什么需要 MAX?
    • MAX() 为您提供一个标量结果,如果任何记录符合您的条件,它将是 'Y',否则它将是 e'N'
    • 太混乱了,难以理解。稍后会阅读该内容并试图解决问题的人会生气。
    【解决方案2】:

    BULK COLLECT 只是一种用多行结果集填充 PL/SQL 集合(数组)的方法。没有它,我们只能用单行填充标量值。

    在性能方面,最大的影响实际上是查询的效率,您可以按照通常的方式进行调整。否则,BULK COLLECT 的性能在很大程度上是透明的 = 除非您选择了很多(数千)行。这很重要,因为集合驻留在会话级内存中,因此如果您的 PGA 配置不当,非常大的集合(很多行、很多列)可能会导致分页(写入磁盘)。

    如果您遇到内存问题,您可以使用 BULK COLLECTLIMIT 子句来获取记录的小子集并使用流水线函数实现将它们吐出。但是您确实应该首先查看填充查询的性能。

    所以从数组中查找一个值是 O(n)?

    遍历集合是线性的(充其量)。使用 SQL 限制结果集通常比选择所有内容并在循环中过滤结果集更有效。 SQL 在处理集合方面效率很高。换句话说,Kaushik's solution

    【讨论】:

      【解决方案3】:

      这将更具可读性。当然,您可以将索引放在表中的id 字段上。 如果id 不是主键(即可能有重复项),请在WHERE 子句中使用ROWNUM = 1

      FUNCTION foo(p_id NUMBER, p_category VARCHAR) RETURN CHAR IS
      n NUMBER;
      BEGIN
          SELECT id INTO n FROM table WHERE id = p_id AND p_category = 'FOO';
          RETURN 'Y';
      EXCEPTION WHEN OTHERS THEN
          RETURN 'N';
      END;
      

      【讨论】:

      • 当该 id 没有值时,这将引发 no data found 。你所说的混乱是为了避免这种情况。
      • 这假设(ID, CATEGORY) 形成一个唯一的键,我们不知道是这样的。此外,使用 WHEN OTHERS 而不是 WHEN NO_DATA_FOUND 是不好的做法。更一般地说,使用异常处理程序来管理有效状态的优点值得商榷。
      猜你喜欢
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多