在集合类型列中快速搜索

时间:2016-10-17 12:37:33

标签: oracle plsql oracle12c

创建集合类型:

CREATE TYPE nums_list AS TABLE OF NUMBER;

使用集合类型列(嵌套表列)创建表:

CREATE TABLE test1 (
        num NUMBER,
        tagged nums_list
)
NESTED TABLE tagged STORE AS mytest_tagged_table;

在表格中插入1百万行:

DECLARE 
    tagg_value nums_list := nums_list(3,4,5);
BEGIN
    for i in 1..1000000 loop
          if i = 600000 then
              tagg_value := nums_list(7,8);
          end if;

          INSERT INTO test1
          (num, tagged)
          VALUES
          (i, tagg_value);
    end loop;
END;

然后运行查询以搜索集合类型中的元素:

    select count(*) from test1 where 8 member of tagged;

此查询运行缓慢,执行时间约为7-8秒。

问题:如何加快执行时间?可能是索引?但是如何使用嵌套表列的索引我没有。

P.S。我尝试使用循环检查PL / SQL块中的每一行,使用游标然后将结果作为流水线表函数返回,但这比直接查询更慢。

1 个答案:

答案 0 :(得分:3)

如果您根据示例对此查询执行EXPLAIN PLAN

select count(*) from test1 where 8 member of tagged;

...您将看到Oracle可能 使用mytest_tagged_table上的(系统生成的)索引来帮助提高性能。它仍然需要这么长时间的原因是400,000个索引查找实际上 效率低于仅读取整个表。

所以,问题不是"我怎样才能让Oracle在我的嵌套表中使用索引"?它是如何让Oracle 的?

由于您的tagged列表似乎很小,因此您可以使用VARRAY。这些内容可以内联存储以获得更好的性能,但相关的语法并不是干净的。

以下是您为VARRAY修改的示例:

CREATE NONEDITIONABLE TYPE nums_varray AS VARRAY(10) OF NUMBER;

CREATE TABLE test2 (
        num NUMBER,
        tagged nums_varray
);

INSERT INTO test2
SELECT rownum,
       case when rownum < 600000 then new nums_varray(3,4,5) else new nums_varray(7,8) end
FROM   dual
connect by rownum <= 1000000;


select count(*) from test2 
where exists ( 
   SELECT '8 in list' 
   FROM TABLE(tagged) 
   WHERE column_value = 8);

在我的系统上,这只需要3,600个缓冲区才能运行 - 而2.1 百万缓冲区则需要你的示例查询。相应地,它也运行得更快。

VARRAYS不是直接等效于嵌套表,它们带有警告。但是,根据你的例子,它们可能就是你要找的东西。