0

运行输入为 ~5M obs 的程序时出现内存不足错误。和 153 个变量。

在 ~40,000 obs 上运行相同的程序时。- 程序执行并完成得很好。当我尝试增加输入 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;
4

4 回答 4

1

基于此:“我知道它在哪个数据步骤上将我抛出。问题是,它是一个数据 null 根据 if 语句调用不同的宏。”

看看是如何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合理的大小。这应该可以防止您内存不足。

于 2014-01-07T13:01:08.703 回答
0

根据编辑和您的评论,我怀疑“order by”和/或“proc sort”部分无法处理它正在运行的系统上的音量。

50M 是很多记录,但大多数人仍然可以管理。但是,如果您的数据增长到 5 亿条记录,则可能太多了。

我记得我不久前有一个客户,其中数据集是 120M 行和 (iirc) +-300 个变量,我们确实遇到了类似的问题。
幸运的是,有一些方法可以处理大量数据。

1. 使用 tagsort 选项
您可以将 tagsort 作为选项添加到 proc sort 语句中。在这种情况下,SAS 仅使用 by 语句中的列进行排序,然后附加记录的剩余部分。它占用的资源较少,但当然速度较慢。

2. 为 by 语句使用索引
如果您需要稍后在 proc/data 步骤中为 by 语句按特定顺序排列数据,您可以在这些变量上创建索引,而不是对数据进行排序。我的经验是,这将使 SAS 也能够处理更大的数据集。当然,它更慢,它消耗更多空间(用于索引)并且您需要考虑索引的存在(和破坏)。

3. 拆分数据集,对部分进行排序,然后将所有内容拼接在一起
最后一种方法(在许多情况下可能比选项 2 更可取)是:

  1. 将数据集拆分为更小的数据集。
  2. 对每个较小的数据集进行排序。
  3. 使用简单的数据步骤将所有内容重新组合在一起。(将所有较小的数据集放在 set 语句中,并使用您排序的 by 语句)

这个列表方法(和标签排序)在这里解释:http: //www.nesug.org/Proceedings/nesug12/cc/cc36.pdf

请注意,所有这些方法都要求您摆脱任何 order by 并使用适当的排序过程跟进这些 proc sql 片段。

于 2014-01-06T13:04:46.957 回答
0

首先,您需要检查为您的 sas 会话和排序分配了多少磁盘空间。这些选项称为 MEMSIZE 和 SORTSIZE

运行此代码,您将在日志中看到以字节为单位的值:

proc options group=memory option=(memsize sortsize) ; run;

我建议将此行添加为代码中的第一行,以将 MAX 空间分配给排序大小:options sortsize=MAX;看看这是否解决了问题。

否则,您可以将 MEMSIZE 更改为 MAX,按照本文中步骤操作。

于 2018-05-10T15:28:54.707 回答
0

添加%nrstr()到您的 CALL EXECUTE 语句中。

CALL EXECUTE ('%nrstr(%STORNO_TKUFA) ('||POLICY_RK||');');
CALL EXECUTE ('%nrstr(%UPDATE) (STORNO_TKUFA_CUMULATE);');

或者也许更好地更改您的数据 _null_ 步骤以生成包含代码的文件并 %include 文件。

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 ; 
于 2018-05-10T16:46:58.747 回答