创建集合类型:
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块中的每一行,使用游标然后将结果作为流水线表函数返回,但这比直接查询更慢。
答案 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
不是直接等效于嵌套表,它们带有警告。但是,根据你的例子,它们可能就是你要找的东西。