当运行输入为~5M obs的程序时,我出现Out Of Memory错误。和153个变量。
在~40,000 obs上运行相同的程序时。 - 程序执行并完成很好。 当我尝试增加输入数量的时候。超过100K - 我收到一个错误:内存不足。
我尝试按照以下提示操作,取消选中几个框:
1.Tools ► Options ► Results General ► deselect all Result Formats.
2.Tools ► Options ► Results General ► deselect Open generated data/results automatically.
3.Tools ► Options ► Results General ► deselect Link handcoded ODS results.
4.Tools ► Options ► SAS Programs ► deselect Automatically direct results back to SAS Enterprise Guide.
仍然 - 不工作。
我使用的是Enterprise Guide 5.1 但最终会将工作代码插入到Data Integration Studio 4.6上的用户书面代码转换中。
有没有人知道如何让这个程序运作?
的编辑 的
这是导致错误消息的一段代码:
data _null_;
set all_include_Stornos ;
IF TREATMENT_IND = 1 AND DDS_ROW_IND NE 1 THEN DO;
CALL EXECUTE ('%STORNO_TKUFA ('||POLICY_RK||');');
CALL EXECUTE ('%UPDATE (STORNO_TKUFA_CUMULATE);');
END;
IF TREATMENT_IND in (4) AND DDS_ROW_IND NE 1 THEN DO;
CALL EXECUTE ('%HAKPAA ('||POLICY_RK||','||POLICY_VERSION||');');
call execute ('%UPDATE(HAKPAA_CUMULATE);');
END;
IF TREATMENT_IND = 5 AND DDS_ROW_IND NE 1 and count_bitul_no <2 or (count_bitul_no >1 and max_bitul_ver = policy_verSion ) THEN DO;
CALL EXECUTE ('%BITUL ('||POLICY_RK||','||POLICY_VERSION||');');
CALL EXECUTE ('%UPDATE(BITUL_CUMULATE);');
END;
IF TREATMENT_IND = 6 AND DDS_ROW_IND NE 1 THEN DO;
CALL EXECUTE ('%LAST_STATE ('||POLICY_RK||','||POLICY_VERSION||');');
CALL EXECUTE ('%UPDATE (LAST_STATE_calc);');
END;
IF DDS_ROW_IND NE 1 and ((PREV_TREATMENT_IND = 4 AND TREATMENT_IND NOT IN (1,2,5)) or treatment_ind = 3) THEN DO;
CALL EXECUTE ('%HAFSHARA ('||POLICY_RK||','||POLICY_VERSION||');');
CALL EXECUTE ('%UPDATE (HAFSHARA_CUMULATE);');
END;
IF TREATMENT_IND = 2 AND POLICY_VERSION - 1 = max_bitul_ver AND DDS_ROW_IND NE 1 THEN DO;
CALL EXECUTE ('%STORNO_BITUL ('||POLICY_RK||','||POLICY_VERSION||');');
CALL EXECUTE ('%UPDATE (STORNO_BITUL_CUMULATE);');
END;
RUN;
这些是当treatment_ind = 5时执行的2个宏(缩短):
%macro BITUL (pol_rk , pol_ver );
proc sql;
create table macro_BITUL
as select * from all_include_Stornos
where policy_rk = &pol_rk
and treatment_ind_5 = &pol_ver
order by policy_rk, policy_version;
quit;
data BITUL_calc;
set macro_BITUL;
BY POLICY_RK;
IF LAST.policy_rk THEN ACT_DAILY_AMT_END_DT = POLICY_VERSION_END_DT;
ELSE ACT_DAILY_AMT_END_DT = NEXT_POLICY_VERSION_START_DT;
VERSION_EXPOSURE_DAYS_NO = ACT_DAILY_AMT_END_DT - ACT_DAILY_AMT_START_DT + 1;
BITUL_DURATION = (POLICY_EXPIRATION_DT_5 - POLICY_VERSION_START_DT + 1) / (POLICY_VERSION_END_DT_5 - POLICY_VERSION_START_DT + 1);
GAINED_NET_PREMIUM_V_AMT = NET_PREMIUM_V_AMT *BITUL_DURATION;
.
.
.
GAINED_NET_COMMISION_B_IB_V_AMT = PRODUCR_B_NET_COMM_IB_V_AMT * BITUL_DURATION;
run;
/**/
PROC SQL;
CREATE TABLE TOTAL_GAINED AS
SELECT POLICY_RK,
SUM(GAINED_NET_PREMIUM_V_AMT) AS TOT_GAINED_NET_PREMIUM_V_AMT,
SUM(GAINED_NET_FEES_V_AMT) AS TOT_GAINED_NET_FEES_V_AMT,
.
.
.
SUM(GAINED_NET_COMMISION_B_IB_V_AMT) AS TOT_GAINED_NET_COMMN_B_IB_V_AMT
FROM BITUL_calc
GROUP BY POLICY_RK;
QUIT;
PROC SQL;
CREATE TABLE BITUL_calc_AND_TOTALS AS
SELECT A.* ,
TOT_GAINED_NET_PREMIUM_V_AMT,
.
.
JOIN TOTAL_GAINED AS B
ON
(A.POLICY_rK = B.POLICY_RK
)order by policy_rk, policy_version;
QUIT;
DATA bitul_CALCULATED;
SET BITUL_calc_AND_TOTALS;
IF TOT_GAINED_NET_PREMIUM_V_AMT = 0 THEN CALCULATED_NET_PREMIUM_V_AMT = 0;
ELSE CALCULATED_NET_PREMIUM_V_AMT = NET_PREMIUM_AMT_5 * GAINED_NET_PREMIUM_V_AMT / TOT_GAINED_NET_PREMIUM_V_AMT;
.
.
ELSE CALC_NET_COMMISION_B_IB_V_AMT = PRODUCR_B_NET_COMM_IB_AMT_5 * GAINED_NET_COMMISION_B_IB_V_AMT / TOT_GAINED_NET_COMMN_B_IB_V_AMT;
.
.
.
.
.
run;
DATA BITUL_CUMULATE;
SET bitul_CALCULATED;
.
.
.
.
.
.
run;
%mend ;
%MACRO UPDATE (TABLE_NAME);
PROC SQL;
DELETE FROM all_include_Stornos
WHERE CATS(POLICY_RK,POLICY_VERSION) IN ( SELECT CATS(POLICY_RK,POLICY_VERSION) FROM &TABLE_NAME);
INSERT INTO all_include_Stornos
select * FROM &TABLE_NAME
;QUIT;
/* PROC SORT DATA=all_include_Stornos OUT=all_include_Stornos; BY POLICY_RK POLICY_VERSION;RUN;*/
%MEND;
答案 0 :(得分:1)
基于此:“我知道它抛出了哪个数据步骤。事实上,根据if语句,它是一个数据null调用不同的宏。”
了解Call Execute
的工作原理。 (http://www2.sas.com/proceedings/sugi22/CODERS/PAPER70.PDF会很有帮助)
基本上,Call Execute
将立即解析宏代码,但它会将生成的SAS步骤排队,直到当前数据步骤结束。换句话说,您可能在内存中构建了数百万行SAS代码,而SAS只是在data _null_;
步骤结束时存储起来执行。最终,这变得如此之大,以至于SAS只是掏空了。
如何处理?只需编写一个宏来将data _null_;
步骤分成块。您可以使用proc sql
在all_include_Stornos
中选择宏变量中的记录数。然后使用宏循环多次运行数据步骤,使用firstobs
和obs
每次只能命中一部分数据。这样,您可以将call execute
构建的缓冲区保持在合理的大小。这样可以防止内存不足。
答案 1 :(得分:0)
根据编辑和评论,我怀疑'order by'和/或'proc sort'部分无法处理正在运行的系统上的音量。
50M是很多记录,但大多数仍然可以管理。
但是,如果您的数据增长到500M记录,那可能会太多。
我记得我刚才有一个客户端数据集是120M行和(iirc)+ -300变量,我们确实得到了类似的问题。
幸运的是,有一些方法可以处理大量数据。
的 1。使用tagsort选项
您可以将tagsort添加为proc排序语句的选项。在这种情况下,SAS仅使用by语句中的列进行排序,然后附加记录的剩余部分。它的资源密集程度较低,但当然速度较慢。
的 2。使用索引的索引
如果稍后需要在proc / data步骤中为by语句按特定顺序使用数据,则可以在这些变量上创建索引,而不是对数据进行排序。我的经验是,这将使SAS能够应对更大的数据集。当然,它更慢,它消耗更多的空间(对于索引),你需要考虑索引的存在(和破坏)。
第3。拆分数据集,对零件进行排序,然后将所有零件拼接在一起
最后一种方法(在许多情况下可能更适合选项2)是:
此列表方法(和tagsort)在此解释:http://www.nesug.org/Proceedings/nesug12/cc/cc36.pdf
请注意,所有这些方法都要求您通过适当的排序过程来删除任何顺序并跟进这些proc sql文件。
答案 2 :(得分:0)
首先,您需要检查为sas会话和排序分配了多少磁盘空间。这些选项称为MEMSIZE和SORTSIZE
运行此代码,您将在日志中看到以字节为单位的值:
proc options group=memory option=(memsize sortsize) ; run;
我建议将此行添加为代码中的第一行,以将MAX空间分配给排序大小:options sortsize=MAX;
并查看是否解决了此问题。
否则,您可以将MEMSIZE更改为MAX,按照此post中的步骤操作。
答案 3 :(得分:0)
将%nrstr()
添加到CALL EXECUTE语句中。
CALL EXECUTE ('%nrstr(%STORNO_TKUFA) ('||POLICY_RK||');');
CALL EXECUTE ('%nrstr(%UPDATE) (STORNO_TKUFA_CUMULATE);');
或者更好地更改数据_null_步骤以生成包含代码的文件,%包含文件。
filename code temp;
data _null_;
set all_include_Stornos ;
IF TREATMENT_IND = 1 AND DDS_ROW_IND NE 1 THEN DO;
put '%STORNO_TKUFA (' POLICY_RK ');';
put '%UPDATE (STORNO_TKUFA_CUMULATE);';
...
RUN;
%include code ;