簡體   English   中英

優化SAS Proc SQL查詢

[英]Optimize SAS Proc SQL query

我試圖加入2個大表,以便根據第二個表中的字段對第一條記錄進行分組。 左表具有大約5,000萬條事件記錄,右表具有大約3500萬條每月間隔記錄。 每月間隔處於subjID級別,因此我無法僅保留開始日期和結束日期來減小右表的大小。 目前,執行加入大約需要40-60分鍾。

我嘗試在subjID,eventDate,startDate和endDate上創建簡單的索引,但是它似乎並沒有提高性能(創建索引的時間大約是5分鍾,而聯接的時間是38分鍾)。

我還有其他選擇可以用來改善處理效果嗎?

在subjID級別的事件左表:

data eventsTable;
input @1 subjID 8.
    @10 eventDate date9.;
format eventDate mmddyy10.;
datalines;
101      01AUG2011
101      28AUG2011
101      30AUG2011
101      01SEP2011
101      12SEP2011
101      28SEP2011
102      01JAN2015
102      15JAN2015
102      01FEB2015
102      16FEB2015
;
run;

在subjID級別的每月間隔右表。 如果事件發生在開始日期和結束日期之間,我正在嘗試將endDate帶入事件:

data monthlyTable;
input @1 subjID 8.
    @10 startDate date9. 
    @22 endDate date9.;
format startDate endDate mmddyy10.;
datalines;
101      28JUL2011   30AUG2011
101      30AUG2011   28SEP2011
101      28SEP2011   28OCT2011
102      01DEC2014   02JAN2015
102      02JAN2015   02FEB2015
102      02FEB2015   02MAR2015
;
run;

輸出:

proc sql;
create table wantTable as 
    select a.*,
        endDate as monthlyDate
    from eventsTable a left join monthlyTable b on 
        a.subjID = b.subjID
    where a.eventDate > b.startDate and a.eventDate <= b.endDate
        order by subjID, eventDate;
quit;

如果你有足夠的內存,你只需要在enddatemonthlyTable ,你可能會發現的格式合並是這樣做的更有效的方法。 但是,如果兩個數據集都很大,那么您只能期望有太多的優化,因為您總是必須至少完全讀取每個數據集。

data t_format(keep = fmtname--hlo) /view = t_format;
  set monthlytable(keep = subjID startdate enddate) end = eof;
  retain fmtname 'myinfmt' type 'i';
  length start end $18; /*Increase for IDs longer than 8 digits*/
  start = cats(put(subjID,z8.),put(startdate + 1,yymmdd10.));
  end   = cats(put(subjID,z8.),put(enddate,yymmdd10.));
  label = enddate;
  output;
  if eof then do;
    hlo = 'O';
    label = .N;
    output;
  end;
run;

proc format cntlin = t_format;
run;

data want;
  set eventstable;
  enddate = input(cats(put(subjID,z8.),put(eventdate,yymmdd10.)),myinfmt18.);
  format enddate yymmdd10.;
run;

請注意yymmdd10.的使用yymmdd10. z8. 格式-這些格式可確保鍵始終具有相同的長度,避免產生歧義,並且在創建數字信息myinfmt升序正確指定查找值的范圍。 嚴格來說,我想這是一個信息合並而不是格式合並,但這是同一種想法。

如果要通過這種方法返回多個查找變量,則需要在定義格式時將它們串聯在一起,然后在應用格式后將其拆分。

我估計這種方法需要為您指定的數據集存儲約1.5GB的內存-即(18個字節x 2個日期范圍+ 8個字節的格式化值)x 35m行。 根據您ID的長度,這可能會有所不同。

如果需要多個查找值,則可以使用哈希合並來執行類似的操作,但是我懷疑在這種情況下格式合並會更有效。

一種可能的哈希合並方法如下所示:

data t_lookup /view= t_lookup;
  set monthlytable;
  by subjID;
  if first.subjID then id_range_count = 0;
  id_range_count + 1;
run;

data want;
  set eventstable;
  if _n_ = 1 then do;
    if 0 then set monthlytable(keep = subjID startdate enddate); /*Add extra lookup vars here as needed*/
    declare hash h(dataset:"t_lookup");
    rc = h.definekey("subjID","id_range_count");
    rc = h.definedata("startdate","enddate"); /*Add extra lookup vars here as needed*/
    rc = h.definedone();
  end;
  match = 0;
  rc    = 0;
  do id_range_count = 1 by 1 while(rc = 0 and match = 0);
    rc = h.find();
    match = startdate < eventdate <= enddate;
  end;
  if match = 0 then call missing(startdate,enddate);
  drop rc match id_range_count;
run;

對於您的查詢而言,最佳索引是對monthlyTable(subjId, startDate, endDate)的綜合索引。 但是,我不確定這對SAS的性能是否會有很大的改善。

預排序數據集比創建索引要好。 但是,預排序可能會花費很長時間,具體取決於數據集的大小以及要對它們進行排序的內容。 它可能需要比原始SQL查詢更長的時間,因此測試變得很重要。

嘗試跑步

PROC SORT DATA=eventsTable ;
  BY subjID eventDate ;
RUN ;

PROC SORT DATA=monthlyTable ;
  BY subjID startDate endDate ;
RUN ;

在您的PROC SQL之前。 我唯一的解釋是,SAS可以識別SORT BY標頭信息,並且無需掃描整個表以查找聯接,因為給定的subjID可能僅在幾個連續的頁面上。 在幾個連續的頁面上也會減少I / O。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM