我有一个场景,我正在创建一个临时表,其中包含来自select语句的数据。我的问题是当来自select查询的数据很大时,我遇到的内存问题不足导致我的查询无法给出结果。
我想知道是否有办法将一大块数据(比如每1000行)提交到临时表中,然后再转到下一个。
Eg:
CREATE TABLE NEW_TABLE AS
SELECT [ column1, column2...columnN ]
FROM EXISTING_TABLE
[ WHERE ] <ALL CONDITIONS>
现在让我们假设内部选择返回100行。我不希望所有100行一次插入NEW_TABLE。我想分开这个。我该如何有效地做到这一点?
答案 0 :(得分:0)
如果您创建临时表,为什么不将表创建为 GLOBAL TEMPORARY TABLE ,这样? :
CREATE GLOBAL TEMPORARY TABLE NEW_TABLE AS
SELECT [ column1, column2...columnN ]
FROM EXISTING_TABLE
[ WHERE ] <ALL CONDITIONS>
ON COMMIT DELETE ROWS;
由于“重做生成减少,因此根据定义,它们不进行日志记录。”(http://psoug.org/reference/gtt.html)
阐述我写的内容:
“重做记录缓存在 重做日志中的循环时尚 SGA的缓冲区(参见“Oracle如何 数据库写入重做日志“) 并写入重做之一 日志编写器(LGWR)的日志文件 数据库后台进程。“ - docs.oracle.com/cd/B28359_01/server.111/b28310/onlineredo001.htm
使用global temporary可以避免冗余内存成本。我认为你不关心安全临时数据。除了Global Temporary Table,默认值被写入临时表空间,该表空间针对瞬态数据的存储进行了优化。
“当Oracle需要将数据存储在全局临时表中或为散列连接构建哈希表时,Oracle还会在内存中启动操作,并在所涉及的数据量足够小的情况下完成任务而无需写入磁盘。虽然填充全局临时表或构建哈希不是排序操作,但我们将在本文中将所有这些活动混为一谈,因为它们以类似的方式由Oracle处理。
如果某个操作占用了一定量的内存,那么Oracle会将操作分成较小的操作,每个操作都可以在内存中执行。部分结果将在临时表空间中写入磁盘。“
基于: - 你使用的是除默认进程内存(sga,undo)之外的其他内存区域,在你的情况下看起来很小 - 当内存大小不足时 - &gt; oracle会将数据写入磁盘
答案 1 :(得分:0)
行。我想我有一个临时解决方案/解决我的问题:这样的事情:
DECLARE
counter number (6) := 1;
cursor c1 is
<select query>
type t__data is table of c1%rowtype index by inary_integer;
t_data t__data;
begin
open c1;
loop
fetch c1 bulk collect into t_data;
exit when t_data.count = 0;
for idx in t_data.first .. t_data.last loop
insert into TEMP_ONE1 (x,y)
values (t_data(idx).x, t_data(idx).y);
counter := counter + 1;
if counter = 10000
then
counter := 0;
commit;
end if;
end loop;
end loop;
close c1;
end;
您认为这是解决问题的好方法吗? (我运行查询以获取一小部分数据,但确实有效)