oracle中避免全局临时表的方法
我们刚刚将sql server存储过程转换为oracle过程。Sql Server SP高度依赖于插入到表1中的会话表。。。这些表在oracle中被转换为全局临时表。我们的400个SP最终得到了大约500 GTT 现在我们发现,由于性能和其他问题,在oracle中使用GTT被认为是最后的选择 还有其他的选择吗?收藏?光标 我们对GTT的典型使用如下: 插入GTToracle中避免全局临时表的方法,oracle,plsql,temp-tables,Oracle,Plsql,Temp Tables,我们刚刚将sql server存储过程转换为oracle过程。Sql Server SP高度依赖于插入到表1中的会话表。。。这些表在oracle中被转换为全局临时表。我们的400个SP最终得到了大约500 GTT 现在我们发现,由于性能和其他问题,在oracle中使用GTT被认为是最后的选择 还有其他的选择吗?收藏?光标 我们对GTT的典型使用如下: 插入GTT INSERT INTO some_gtt_1 (column_a, column_b, column_c) (SE
INSERT INTO some_gtt_1
(column_a,
column_b,
column_c)
(SELECT someA,
someB,
someC
FROM TABLE_A
WHERE condition_1 = 'YN756'
AND type_cd = 'P'
AND TO_NUMBER(TO_CHAR(m_date, 'MM')) = '12'
AND (lname LIKE (v_LnameUpper || '%') OR
lname LIKE (v_searchLnameLower || '%'))
AND (e_flag = 'Y' OR
it_flag = 'Y' OR
fit_flag = 'Y'));
更新GTT
UPDATE some_gtt_1 a
SET column_a = (SELECT b.data_a FROM some_table_b b
WHERE a.column_b = b.data_b AND a.column_c = 'C')
WHERE column_a IS NULL OR column_a = ' ';
然后从GTT中获取数据。这些只是示例查询,实际上查询非常复杂,有很多连接和子查询
我有一个三部分的问题:
有人能演示如何转变吗
上面的示例查询
集合和/或游标?
自从
使用GTT,您可以在本地工作
使用SQL…为什么要远离
GTT?他们真的那么糟糕吗。
指导方针应该是什么
何时使用和何时避免GTT
通常,我会使用PL/SQL集合来存储小容量的数据(可能是1000行)。如果数据量大得多,我会使用GTT,这样它们就不会使进程内存过载 因此,我可能会从数据库中选择几百行到PL/SQL集合中,然后遍历它们进行一些计算/删除一些行或其他行,然后将该集合插入到另一个表中 如果我处理的是数十万行,我会尽量将“繁重”的处理过程推进到大型SQL语句中。可能需要也可能不需要GTT 您可以将SQL级别的集合对象用作在SQL和PL/SQL之间非常容易转换的对象
create type typ_car is object (make varchar2(10), model varchar2(20), year number(4));
/
create type typ_coll_car is table of typ_car;
/
select * from table (typ_coll_car(typ_car('a','b',1999), typ_car('A','Z',2000)));
MAKE MODEL YEAR
---------- -------------------- ---------------
a b 1,999.00
A Z 2,000.00
declare
v_car1 typ_car := typ_car('a','b',1999);
v_car2 typ_car := typ_car('A','Z',2000);
t_car typ_coll_car := typ_coll_car();
begin
t_car := typ_coll_car(v_car1, v_car2);
FOR i in (SELECT * from table(t_car)) LOOP
dbms_output.put_line(i.year);
END LOOP;
end;
/
让我们先回答第二个问题:
为什么要远离GTT?是吗
真的那么糟糕
几天前,我找到了一个概念验证,它将一个18MB的大型XML文件加载到一个XMLType中。因为我不想永久存储XMLType,所以我尝试将其加载到PL/SQL变量会话内存和临时表中。将其加载到临时表中所花的时间是将其加载到XMLType变量中所花时间的五倍,即5秒,而不是1秒。区别在于临时表不是内存结构:它们被写入磁盘,特别是您指定的临时表空间
如果您想缓存大量数据,那么将其存储在内存中会给PGA带来压力,如果您有大量会话,这是不好的。所以这是RAM和时间之间的权衡
关于第一个问题:
有人能告诉我如何改变这个世界吗
上面是对集合的示例查询
和/或游标
您发布的查询可以合并到单个语句中:
SELECT case when a.column_a IS NULL OR a.column_a = ' '
then b.data_a
else column_a end AS someA,
a.someB,
a.someC
FROM TABLE_A a
left outer join TABLE_B b
on ( a.column_b = b.data_b AND a.column_c = 'C' )
WHERE condition_1 = 'YN756'
AND type_cd = 'P'
AND TO_NUMBER(TO_CHAR(m_date, 'MM')) = '12'
AND (lname LIKE (v_LnameUpper || '%') OR
lname LIKE (v_searchLnameLower || '%'))
AND (e_flag = 'Y' OR
it_flag = 'Y' OR
fit_flag = 'Y'));
我只是简单地转换了你的逻辑,但是这个case语句可以用一个更简洁的nvl2trima.column_a,a.column_a,b.data_a替换
我知道你说你的查询更复杂,但是你的第一个端口应该是考虑重写它们。我知道将一个粗糙的查询分解成许多用PL/SQL缝合在一起的小SQL是多么诱人,但纯SQL更有效
要使用集合,最好在SQL中定义类型,因为它使我们能够灵活地在SQL语句和PL/SQL中使用它们
create or replace type tab_a_row as object
(col_a number
, col_b varchar2(23)
, col_c date);
/
create or replace type tab_a_nt as table of tab_a_row;
/
下面是一个示例函数,它返回一个结果集:
create or replace function get_table_a
(p_arg in number)
return sys_refcursor
is
tab_a_recs tab_a_nt;
rv sys_refcursor;
begin
select tab_a_row(col_a, col_b, col_c)
bulk collect into tab_a_recs
from table_a
where col_a = p_arg;
for i in tab_a_recs.first()..tab_a_recs.last()
loop
if tab_a_recs(i).col_b is null
then
tab_a_recs(i).col_b := 'something';
end if;
end loop;
open rv for select * from table(tab_a_recs);
return rv;
end;
/
这就是行动:
SQL> select * from table_a
2 /
COL_A COL_B COL_C
---------- ----------------------- ---------
1 whatever 13-JUN-10
1 12-JUN-10
SQL> var rc refcursor
SQL> exec :rc := get_table_a(1)
PL/SQL procedure successfully completed.
SQL> print rc
COL_A COL_B COL_C
---------- ----------------------- ---------
1 whatever 13-JUN-10
1 something 12-JUN-10
SQL>
在函数中,有必要用列实例化类型,以避免ORA-00947异常。填充PL/SQL表类型时,这不是必需的:
SQL> create or replace procedure pop_table_a
2 (p_arg in number)
3 is
4 type table_a_nt is table of table_a%rowtype;
5 tab_a_recs table_a_nt;
6 begin
7 select *
8 bulk collect into tab_a_recs
9 from table_a
10 where col_a = p_arg;
11 end;
12 /
Procedure created.
SQL>
最后,准则
什么时候应该有什么指导方针
使用和何时避免GTT
当我们需要在同一会话中的不同程序单元之间共享缓存数据时,全局临时表非常好。例如,如果我们有一个通用的报告结构,它是由一个单一的函数生成的,该函数由几个过程中的一个填充GTT。尽管这也可以通过动态引用游标实现
如果我们有很多中间处理,而这些中间处理太复杂,无法用一个SQL查询来解决,那么全局临时表也很好。尤其是当必须对检索到的行的子集应用该处理时
但一般来说,我们不需要使用临时表。所以
在SQL中执行它,除非它太难了,在这种情况下。。。
... 通常在PL/SQL变量集合中执行此操作,除非它占用太多内存,在这种情况下。。。
... 使用全局临时表执行此操作
感谢APC的详细解释。我知道您预先警告过集合的代码未经测试,但我在尝试运行代码时总是得到“值不足”。你能告诉我怎么了吗?当我浏览gui时…tab\u a\u nt没有属性,而as tab\u a\u行有3个定义的属性。我真的很困惑,无法让它工作。你能帮我渡过难关吗?