我有一个数据清理程序,它从两个表的卡行中删除相同的数据。
这两个更新语句都使用相同的子查询来检测应该更新哪些行。
UPDATE table_1 SET card = NULL WHERE id in
(select id from sub_table WHERE /* complex clause here */);
UPDATE table_2 SET card = NULL WHERE id in
(select id from sub_table WHERE /* complex clause here */);
使用 Oracle 临时表是优化我的代码的好解决方案吗?
CREATE TEMPORARY TABLE tmp_sub_table AS
select id from sub_table WHERE /* complex clause here */;
UPDATE table_1 SET card = NULL WHERE id in (select * from tmp_sub_table);
UPDATE table_2 SET card = NULL WHERE id in (select * from tmp_sub_table);
我应该使用 本地临时表或 全局临时 table ?
最佳答案
全局临时表是持久数据结构。当我们 INSERT 将数据写入磁盘时,当我们 SELECT 时从磁盘读取数据。所以磁盘 I/O 相当多:运行相同查询两次所节省的成本必须大于所有这些写入和读取的成本。
需要注意的一件事是 GTT 是建立在临时表空间上的,因此您可能会与其他正在执行排序等长时间运行的进程发生争用。最好有一个单独的临时表空间,仅用于 GTT,但数量不多DBA 这样做。
另一种解决方案是使用集合将记录的子集存储在内存中并使用批量处理。
declare
l_ids sys.ocinumberlist;
cursor l_cur is
select id from sub_table WHERE /* complex clause here */
order by id
;
begin
open lcur;
loop
fetch lcur bulk collect into l_ids limit 5000;
exit when l_ids.count() = 0;
update table1
set card=null
where id member of l_ids;
update table2
set card=null
where id member of l_ids;
end loop;
end;
"updating many rows with one update statement ... works much faster than updating separately using Looping over cursor"
这是正常的建议。但这是一个批量操作:它一次更新五千行,所以它比逐行更快。批处理的大小由
BULK COLLECT ... LIMIT
控制。子句:您不希望将值设置得太高,因为集合在 session 内存中,但由于您只选择一列 - 和一个数字 - 也许您可以将其设置得更高。与往常一样,调整是 的问题对标 .您是否确定运行此子查询两次是一项高成本操作?
select id from sub_table WHERE /* complex clause here */
如果它看起来太慢,您需要测试其他方法并查看它们是否更快。也许全局临时表比批量操作更快。通常内存访问比磁盘访问快,但您需要查看哪种方法最适合您。
关于oracle - Oracle中使用临时表优化SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45297325/