[英]Understanding 'BULK COLLECT' in Oracle Function
Given the following Oracle function: 鉴于以下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;
What's the nature of the lookup of: 查找的本质是什么:
SELECT my_id BULK COLLECT INTO my_array FROM my_table
Or, put differently, is there anything that I can add to this line or elsewhere to speed up the look-up - perhaps an index? 或者换句话说,有什么我可以添加到此行或其他地方以加快查找速度的方法-也许是索引?
All you could do is to use a single select with MAX
or COUNT
您所能做的就是对MAX
或COUNT
使用单个选择
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;
This relies on the fact that string "Y" > "N" . 这取决于字符串“ Y”>“ N”的事实。 You may also use COUNT(CASE ..
and another case where count > 1 THEN 'Y'
您也可以使用COUNT(CASE ..
和另外一种情况where count > 1 THEN 'Y'
Adding an index on id (or other columns referred from the table ) will help to speed up the query 在id(或表中引用的其他列)上添加索引将有助于加快查询速度
Note that it is better to use procedure arguments of the form p_id
and p_category
to avoid conflict 请注意,最好使用格式为p_id
和p_category
过程参数以避免冲突
BULK COLLECT
is simply a method for populating an PL/SQL collection (array) with a result set of multiple rows. BULK COLLECT
只是一种使用多行结果集填充PL / SQL集合(数组)的方法。 Without it we're restricted to populating a scalar value with a single row. 没有它,我们只能使用单行填充标量值。
In terms of performance, the biggest impact is actually the efficiency of the query, which you can tune in the usual fashion. 在性能方面,最大的影响实际上是查询的效率,您可以按照通常的方式进行调整。 Otherwise, the performance of BULK COLLECT
is largely transparent = unless you're selecting lots (thousands) of rows. 否则, BULK COLLECT
的性能在很大程度上是透明的=除非您选择大量(数千)行。 That matters because collections reside in session level memory, so very big collections (lots of rows, many columns) can lead to paging (writing to disk) if your PGA is not configured well. 这很重要,因为集合驻留在会话级内存中,因此,如果您的PGA配置不正确,那么非常大的集合(许多行,许多列)可能导致分页(写入磁盘)。
If you are running into memory problems you could use BULK COLLECT
with the LIMIT
clause to fetch small subsets of the records and spit them out using a pipelined function implementation. 如果遇到内存问题,可以将BULK COLLECT
与LIMIT
子句一起使用,以获取记录的小子集,并使用流水线函数实现将其吐出。 But you really should look at the performance of the populating query first. 但是,您确实应该首先查看填充查询的性能。
So looking up a value form the array is O(n)? 那么从数组中查找一个值是O(n)吗?
Looping through a collection is linear (at best). 在一个集合中循环是线性的(最好)。 It's usually way more efficient to restrict a result set using SQL than to select everything and filter the result set in a loop. 使用SQL限制结果集通常比选择所有内容并在循环中过滤结果集更有效。 SQL is highly efficient at processing sets. SQL在处理集合方面非常高效。 In other words, Kaushik's solution . 换句话说, Kaushik的解决方案 。
This would be way more readable. 这将更具可读性。 Sure you could put index on id
field in your table. 确保您可以在表的id
字段中放置索引。 If id
is not a primary key (ie there may be duplicates), use ROWNUM = 1
in WHERE
clause. 如果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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.