Sql 在块中移动大量数据
我正在编写一个脚本,在这个脚本中,应根据某些条件查询大量数据,并分别移动到一些存档表中。我有超过五千万条记录要扫描并选择匹配的记录,以便对六个存档表执行插入操作。下面的脚本对大约50万条记录运行良好,但在运行数百万条记录时抛出下面的异常Sql 在块中移动大量数据,sql,oracle,plsql,user-defined-types,bulk-operations,Sql,Oracle,Plsql,User Defined Types,Bulk Operations,我正在编写一个脚本,在这个脚本中,应根据某些条件查询大量数据,并分别移动到一些存档表中。我有超过五千万条记录要扫描并选择匹配的记录,以便对六个存档表执行插入操作。下面的脚本对大约50万条记录运行良好,但在运行数百万条记录时抛出下面的异常 Error report: ORA-04036: PGA memory used by the instance exceeds PGA_ AGGREGATE _LIMIT 除了增加PGA_uuAggregate_u限制之外,我还想改进我的脚本,避免将所有记录
Error report:
ORA-04036: PGA memory used by the instance exceeds PGA_ AGGREGATE _LIMIT
除了增加PGA_uuAggregate_u限制之外,我还想改进我的脚本,避免将所有记录加载到内存中,而是运行脚本并将值分块插入表中。目前我还不知道该怎么做。有人能建议我通过让脚本以批处理方式运行来避免内存不足的问题吗
下面是我脚本的一部分(将值插入四个表中)
创建或替换类型R1\u ID\u类型为数字表;
/
创建或替换类型R5_ID_类型为数字表;
/
声明
R01_ID R1_ID_类型;
R05_ID R5_ID_类型;
开始
--将R5_表和R6_表中5年以上的R05_ID添加到R5_ID_类型嵌套表中
选择R5.R05\u ID作为R05\u ID
批量收集到R05_ID中
从R6_表R6,R5_表R5
其中R5.R05_ID=R6.R06_R05_ID_FK
和R5.R05_DATE_TIME_捕获的集合(和其他PL/SQL构造)存储在会话内存中。(与存储在全局内存中的查询数据不同)。因为会话内存是按每个用户分配的,所以必须有一个限制,因为RAM仍然是一个相对昂贵的资源
所以,你得到了这个错误
ORA-04036: PGA memory used by the instance exceeds PGA_ AGGREGATE _LIMIT
。。。因为您的会话已耗尽分配给PGA(会话可用的内存池)的所有内存
问题是您试图用数百万行填充集合。即使那一排很窄,但还是没有。幸运的是,PL/SQL有一个解决方案:它是LIMIT子句
使用LIMIT,我们可以使用结果集的一个块填充集合,处理它并获得下一个块。没有什么可以改变的:
DECLARE
R01_IDS R1_ID_TYPE;
R05_IDS R5_ID_TYPE;
cursor r5_cur is
SELECT R5.R05_ID
BULK COLLECT INTO R05_IDS
FROM R6_TABLE R6 , R5_TABLE R5
WHERE R5.R05_ID = R6.R06_R05_ID_FK
AND R5.R05_DATE_TIME_CAPTURED <= TRUNC(SYSDATE) - 1825
AND R5.R05_STATUS = 'D'
AND R6.R06_STATUS = 'D';
BEGIN
-- this is new
open r5_cur;
loop
fetch r5_cur
BULK COLLECT INTO R05_IDS limit 100000;
exit when R05_IDS.count() = 0;
-- this is all your code
-- Inserts all the deregistered records which are older than five years from R5_TABLE and R6_TABLE tables to the relevant archive tables
INSERT ALL
INTO R5_TABLE_archived(
R05_ID,
R05_R01_ID_FK,
R05_NUMBER,
R05_NUMBER_TYPE,
R05_STATUS,
R05_GSM_SUBSCRIBER_TYPE
R05_DATE_TIME_CAPTURED)
values (
R5_R05_ID,
R5_R05_R01_ID_FK,
R5_NUMBER,
R5_NUMBER_TYPE,
R5_R05_STATUS,
R5_R05_GSM_SUBSCRIBER_TYPE,
R5_R05_DATE_TIME_CAPTURED)
INTO R6_TABLE_archived(
R06_ID,
R06_R05_ID_FK,
R06_R08_ID_FK,
R06_STATUS,
R06_REFERENCE_NUMBER,
R06_DATE_TIME_CAPTURED,
R06_DATE_EXPIRED)
values (
R6_R06_ID,
R6_R06_R05_ID_FK,
R6_R06_R08_ID_FK,
R6_R06_STATUS,
R6_R06_REFERENCE_NUMBER,
R6_R06_DATE_TIME_CAPTURED,
R6_R06_DATE_EXPIRED)
SELECT R5_R05_ID,
R5_R05_R01_ID_FK,
R5_NUMBER,
R5_NUMBER_TYPE,
R5_R05_STATUS,
R5_R05_GSM_SUBSCRIBER_TYPE,
R5_R05_DATE_TIME_CAPTURED,
R6_R06_ID,
R6_R06_R05_ID_FK,
R6_R06_R08_ID_FK,
R6_R06_CHANGE_SOURCE,
R6_R06_REFERENCE_NUMBER,
R6_R06_DATE_TIME_CAPTURED,
R6_R06_DATE_EXPIRED
FROM
(
SELECT R5.R05_ID R5_R05_ID,
R5.R05_R01_ID_FK R5_R05_R01_ID_FK,
R5.R05_NUMBER R5_NUMBER,
R5.R05_NUMBER_TYPE R5_NUMBER_TYPE,
R5.R05_STATUS R5_R05_STATUS,
R5.R05_GSM_SUBSCRIBER_TYPE R5_R05_GSM_SUBSCRIBER_TYPE,
R5.R05_DATE_TIME_CAPTURED R5_R05_DATE_TIME_CAPTURED,
R6.R06_ID R6_R06_ID,
R6.R06_R05_ID_FK R6_R06_R05_ID_FK,
R6.R06_R08_ID_FK R6_R06_R08_ID_FK,
R6.R06_STATUS R6_R06_STATUS,
R6.R06_REFERENCE_NUMBER R6_R06_REFERENCE_NUMBER,
R6.R06_DATE_TIME_CAPTURED R6_R06_DATE_TIME_CAPTURED,
R6.R06_DATE_EXPIRED R6_R06_DATE_EXPIRED
FROM R6_TABLE R6 , R5_TABLE R5
WHERE R5.R05_ID = R6.R06_R05_ID_FK
AND R5.R05_DATE_TIME_CAPTURED <= TRUNC(SYSDATE) - 1825
AND R5.R05_STATUS = 'D'
AND R6.R06_STATUS = 'D');
--selects all the R01 IDs which matches with the above criteria and copy values to respective archive tables
SELECT UNIQUE R1.R01_ID AS R01_ID
BULK COLLECT INTO R01_IDS
FROM R1_TABLE R1, R5_TABLE R5
WHERE R5.R05_ID IN (Select column_value from table(R05_IDS))
AND R1.R01_ID NOT IN (
SELECT R01.R01_ID
FROM R1_TABLE R01,
R5_TABLE R05
WHERE R05.R05_STATUS != 'D'
AND R01.R01_ID = R05.R05_R01_ID_FK)
AND R1.R01_ID = R5.R05_R01_ID_FK;
--insert R1_TABLE tables values which matches with the above criteria into the R1_TABLE_ARCHIVED table
INSERT ALL
INTO R1_TABLE_ARCHIVED(R01_ID,R01_ID_TYPE,R01_IDENTITY_NUMBER,R01_PASSPORT_COUNTRY,R01_DATE_TIME_CAPTURED)
VALUES (RA1_R01_ID,RA1_R01_ID_TYPE,RA1_R01_IDENTITY_NUMBER,RA1_R01_PASSPORT_COUNTRY,RA1_R01_DATE_TIME_CAPTURED)
SELECT RA1_R01_ID,RA1_R01_ID_TYPE,RA1_R01_IDENTITY_NUMBER,RA1_R01_PASSPORT_COUNTRY,RA1_R01_DATE_TIME_CAPTURED
FROM (
SELECT
r1.R01_ID RA1_R01_ID,
r1.R01_ID_TYPE RA1_R01_ID_TYPE,
r1.R01_IDENTITY_NUMBER RA1_R01_IDENTITY_NUMBER,
r1.R01_PASSPORT_COUNTRY RA1_R01_PASSPORT_COUNTRY,
r1.R01_DATE_TIME_CAPTURED RA1_R01_DATE_TIME_CAPTURED
FROM
R1_TABLE r1
WHERE
r1.R01_ID IN (Select column_value from table(R01_IDS))
);
--insert R2_TABLE tables values which matches with the above criteria into the R2_TABLE_ARCHIVED table
INSERT ALL
INTO R2_TABLE_ARCHIVED(R02_ID,R02_R01_ID_FK,R02_fname,R02_SURNAME,R02_CONTACT_NUMBER,R02_DATE_TIME_CAPTURED)
VALUES(RA2_R02_ID,RA2_R02_R01_ID_FK,RA2_R02_fname,RA2_R02_SURNAME,RA2_R02_CONTACT_NUMBER,RA2_R02_DATE_TIME_CAPTURED)
SELECT RA2_R02_ID,RA2_R02_R01_ID_FK,RA2_R02_fname,RA2_R02_SURNAME,RA2_R02_CONTACT_NUMBER,RA2_R02_DATE_TIME_CAPTURED
FROM (
SELECT
r2.R02_ID RA2_R02_ID,
r2.R02_R01_ID_FK RA2_R02_R01_ID_FK,
r2.R02_fname RA2_R02_fname,
r2.R02_SURNAME RA2_R02_SURNAME,
r2.R02_CONTACT_NUMBER RA2_R02_CONTACT_NUMBER,
r2.R02_DATE_TIME_CAPTURED RA2_R02_DATE_TIME_CAPTURED
FROM
R2_TABLE r2
WHERE
r2.R02_R01_ID_FK IN (Select column_value from table(R01_IDS)));
--All the delete queries to remove the above copied values from the parent tables respectively
DELETE FROM R1_TABLE WHERE R01_ID IN (Select column_value from table(R01_IDS));
DELETE FROM R2_TABLE WHERE R02_R01_ID_FK IN (Select column_value from table(R01_IDS));
DELETE FROM R5_TABLE WHERE R05_R01_ID_FK IN (Select column_value from table(R05_IDS));
DELETE FROM R6_TABLE WHERE R06_R05_ID_FK IN (R05_IDS);
end loop;
close r5_cur;
COMMIT;
END;
/
声明
R01_ID R1_ID_类型;
R05_ID R5_ID_类型;
光标r5_cur为
选择R5.R05\u ID
批量收集到R05_ID中
从R6_表R6,R5_表R5
其中R5.R05_ID=R6.R06_R05_ID_FK
表空间是物理存储的映射。除了要求您的DBA添加另一个数据文件外,没有其他解决方法。非常感谢您的清晰解释。这段代码在我的数据库中运行了一个多小时,返回错误ORA-01653:无法扩展表空间用户01653中8192存档的表R5_table_。00000-“无法将表%s.%s扩展到表空间%s中的%s”*原因:无法为指定表空间中的表段分配所需块数的范围*操作:使用ALTER TABLESPACE ADD DATAFILE语句将一个或多个文件添加到指定的表空间。是否有任何解决此表空间问题的方法?请澄清,我在R5表中有31931421条记录,符合要移动的要求。
DECLARE
R01_IDS R1_ID_TYPE;
R05_IDS R5_ID_TYPE;
cursor r5_cur is
SELECT R5.R05_ID
BULK COLLECT INTO R05_IDS
FROM R6_TABLE R6 , R5_TABLE R5
WHERE R5.R05_ID = R6.R06_R05_ID_FK
AND R5.R05_DATE_TIME_CAPTURED <= TRUNC(SYSDATE) - 1825
AND R5.R05_STATUS = 'D'
AND R6.R06_STATUS = 'D';
BEGIN
-- this is new
open r5_cur;
loop
fetch r5_cur
BULK COLLECT INTO R05_IDS limit 100000;
exit when R05_IDS.count() = 0;
-- this is all your code
-- Inserts all the deregistered records which are older than five years from R5_TABLE and R6_TABLE tables to the relevant archive tables
INSERT ALL
INTO R5_TABLE_archived(
R05_ID,
R05_R01_ID_FK,
R05_NUMBER,
R05_NUMBER_TYPE,
R05_STATUS,
R05_GSM_SUBSCRIBER_TYPE
R05_DATE_TIME_CAPTURED)
values (
R5_R05_ID,
R5_R05_R01_ID_FK,
R5_NUMBER,
R5_NUMBER_TYPE,
R5_R05_STATUS,
R5_R05_GSM_SUBSCRIBER_TYPE,
R5_R05_DATE_TIME_CAPTURED)
INTO R6_TABLE_archived(
R06_ID,
R06_R05_ID_FK,
R06_R08_ID_FK,
R06_STATUS,
R06_REFERENCE_NUMBER,
R06_DATE_TIME_CAPTURED,
R06_DATE_EXPIRED)
values (
R6_R06_ID,
R6_R06_R05_ID_FK,
R6_R06_R08_ID_FK,
R6_R06_STATUS,
R6_R06_REFERENCE_NUMBER,
R6_R06_DATE_TIME_CAPTURED,
R6_R06_DATE_EXPIRED)
SELECT R5_R05_ID,
R5_R05_R01_ID_FK,
R5_NUMBER,
R5_NUMBER_TYPE,
R5_R05_STATUS,
R5_R05_GSM_SUBSCRIBER_TYPE,
R5_R05_DATE_TIME_CAPTURED,
R6_R06_ID,
R6_R06_R05_ID_FK,
R6_R06_R08_ID_FK,
R6_R06_CHANGE_SOURCE,
R6_R06_REFERENCE_NUMBER,
R6_R06_DATE_TIME_CAPTURED,
R6_R06_DATE_EXPIRED
FROM
(
SELECT R5.R05_ID R5_R05_ID,
R5.R05_R01_ID_FK R5_R05_R01_ID_FK,
R5.R05_NUMBER R5_NUMBER,
R5.R05_NUMBER_TYPE R5_NUMBER_TYPE,
R5.R05_STATUS R5_R05_STATUS,
R5.R05_GSM_SUBSCRIBER_TYPE R5_R05_GSM_SUBSCRIBER_TYPE,
R5.R05_DATE_TIME_CAPTURED R5_R05_DATE_TIME_CAPTURED,
R6.R06_ID R6_R06_ID,
R6.R06_R05_ID_FK R6_R06_R05_ID_FK,
R6.R06_R08_ID_FK R6_R06_R08_ID_FK,
R6.R06_STATUS R6_R06_STATUS,
R6.R06_REFERENCE_NUMBER R6_R06_REFERENCE_NUMBER,
R6.R06_DATE_TIME_CAPTURED R6_R06_DATE_TIME_CAPTURED,
R6.R06_DATE_EXPIRED R6_R06_DATE_EXPIRED
FROM R6_TABLE R6 , R5_TABLE R5
WHERE R5.R05_ID = R6.R06_R05_ID_FK
AND R5.R05_DATE_TIME_CAPTURED <= TRUNC(SYSDATE) - 1825
AND R5.R05_STATUS = 'D'
AND R6.R06_STATUS = 'D');
--selects all the R01 IDs which matches with the above criteria and copy values to respective archive tables
SELECT UNIQUE R1.R01_ID AS R01_ID
BULK COLLECT INTO R01_IDS
FROM R1_TABLE R1, R5_TABLE R5
WHERE R5.R05_ID IN (Select column_value from table(R05_IDS))
AND R1.R01_ID NOT IN (
SELECT R01.R01_ID
FROM R1_TABLE R01,
R5_TABLE R05
WHERE R05.R05_STATUS != 'D'
AND R01.R01_ID = R05.R05_R01_ID_FK)
AND R1.R01_ID = R5.R05_R01_ID_FK;
--insert R1_TABLE tables values which matches with the above criteria into the R1_TABLE_ARCHIVED table
INSERT ALL
INTO R1_TABLE_ARCHIVED(R01_ID,R01_ID_TYPE,R01_IDENTITY_NUMBER,R01_PASSPORT_COUNTRY,R01_DATE_TIME_CAPTURED)
VALUES (RA1_R01_ID,RA1_R01_ID_TYPE,RA1_R01_IDENTITY_NUMBER,RA1_R01_PASSPORT_COUNTRY,RA1_R01_DATE_TIME_CAPTURED)
SELECT RA1_R01_ID,RA1_R01_ID_TYPE,RA1_R01_IDENTITY_NUMBER,RA1_R01_PASSPORT_COUNTRY,RA1_R01_DATE_TIME_CAPTURED
FROM (
SELECT
r1.R01_ID RA1_R01_ID,
r1.R01_ID_TYPE RA1_R01_ID_TYPE,
r1.R01_IDENTITY_NUMBER RA1_R01_IDENTITY_NUMBER,
r1.R01_PASSPORT_COUNTRY RA1_R01_PASSPORT_COUNTRY,
r1.R01_DATE_TIME_CAPTURED RA1_R01_DATE_TIME_CAPTURED
FROM
R1_TABLE r1
WHERE
r1.R01_ID IN (Select column_value from table(R01_IDS))
);
--insert R2_TABLE tables values which matches with the above criteria into the R2_TABLE_ARCHIVED table
INSERT ALL
INTO R2_TABLE_ARCHIVED(R02_ID,R02_R01_ID_FK,R02_fname,R02_SURNAME,R02_CONTACT_NUMBER,R02_DATE_TIME_CAPTURED)
VALUES(RA2_R02_ID,RA2_R02_R01_ID_FK,RA2_R02_fname,RA2_R02_SURNAME,RA2_R02_CONTACT_NUMBER,RA2_R02_DATE_TIME_CAPTURED)
SELECT RA2_R02_ID,RA2_R02_R01_ID_FK,RA2_R02_fname,RA2_R02_SURNAME,RA2_R02_CONTACT_NUMBER,RA2_R02_DATE_TIME_CAPTURED
FROM (
SELECT
r2.R02_ID RA2_R02_ID,
r2.R02_R01_ID_FK RA2_R02_R01_ID_FK,
r2.R02_fname RA2_R02_fname,
r2.R02_SURNAME RA2_R02_SURNAME,
r2.R02_CONTACT_NUMBER RA2_R02_CONTACT_NUMBER,
r2.R02_DATE_TIME_CAPTURED RA2_R02_DATE_TIME_CAPTURED
FROM
R2_TABLE r2
WHERE
r2.R02_R01_ID_FK IN (Select column_value from table(R01_IDS)));
--All the delete queries to remove the above copied values from the parent tables respectively
DELETE FROM R1_TABLE WHERE R01_ID IN (Select column_value from table(R01_IDS));
DELETE FROM R2_TABLE WHERE R02_R01_ID_FK IN (Select column_value from table(R01_IDS));
DELETE FROM R5_TABLE WHERE R05_R01_ID_FK IN (Select column_value from table(R05_IDS));
DELETE FROM R6_TABLE WHERE R06_R05_ID_FK IN (R05_IDS);
end loop;
close r5_cur;
COMMIT;
END;
/