2014-10-28 130 views
0

我有2个数据集:t.a有390K行和1个变量,t.b有6000万行和350个变量。 我需要快速加入这些数据集,但我的查询太慢了。如何优化SAS中的proc sql join?

如何优化查询?

我的查询:

proc sql; 
    create table с as 
    select distinct a.REP_CLID, b.REP_DATE, &Score_Column, b.REP_AGE as AGE 
    from a (IDXWHERE =Yes) , 
    &b (IDXWHERE =Yes) 
    where a.rep_clid = b.rep_clid 
+0

在你的数据库中,你有IDXWHERE上的索引吗?尤其是b表。 – Mihai 2014-10-28 08:54:57

+0

是的,我有。使用索引查询大约42分钟,没有他们 - 51分钟。 – user3306125 2014-10-28 09:00:55

+0

我猜rep_clid是主键,你真的需要清楚吗? – Mihai 2014-10-28 09:04:06

回答

1

既然你已经在你的大表B对rep_clid索引,这似乎是一个很好的候选人数据步键合并。调整为感兴趣的需要所以你只是保持变量:

data c; 
    set a; 
    set b key = rep_clid; /*requires unique index on rep_clid to work properly*/ 
    if _IORC_ then do; 
    _ERROR_ = 0; 
    delete; 
    end; 
run; 

将与rep_clid出现在A和B仅返回的记录。然后,您可以使用nodupkey选项通过proc进行重复数据删除。

如果您有关于B A非唯一索引,它仍可以工作,但语法是有点复杂:

data c; 
    set a; 
    do until(eof); 
    set b key = rep_clid end = eof; /*will work with non-unique index on rep_clid*/ 
    if _IORC_ then do; 
     _ERROR_ = 0; 
     delete; 
    end; 
    else output; 
    end; 
run; 
0

性能可以是一个棘手的问题,因为有一个庞大的数字可能影响它的因素。在找到性能最好的方法之前,通常会尝试多种方法来实现相同的目标。

这些表是SAS表还是一个或两个第三方DBMS表?这打开了整个世界的性能问题,我将离开,直到确认。

假设他们都是SAS表,如果你只想从表B中获得列,假设他们都是SAS表,假设& Score_Column在表B中。如果不是,那么这将不起作用。

proc sql; 
    create table с as 
    select distinct b.REP_CLID, b.REP_DATE, &Score_Column, b.REP_AGE as AGE 
    from &b (IDXWHERE =Yes) as  b 
    where b.rep_clid in 
      ( select a.rep_clid 
       from a (IDXWHERE =Yes) 
      ) 
    ; 
Quit; 

或者,您可以使用proc格式,如建议。如果& Score_Column在表格a中,但是如果不是,则可以很容易地修改该示例。

Proc sql; 
     create table rep_clid_fmt as 
     select distinct  'rep_clid_fmt' as fmtname 
     ,  rep_clid      as  start 

/*    If &Score_Column is in table a then use &Score_Column as the label */ 
     ,  &Score_Column     as  label 

       else use a flag like... 
     ,  'keep'       as  label 

     from a 
     ; 
Quit; 

Proc format cntlin=rep_clid_fmt; 
Run; 


proc sql; 
    create table с as 
    select distinct b.REP_CLID 
     , b.REP_DATE 
     , put (b.REP_DATE,rep_clid_fmt) as  &Score_Column 
     , b.REP_AGE as AGE 
    from &b (IDXWHERE =Yes) as  b 
    where put (b.REP_DATE,rep_clid_fmt)  ne substr (b.REP_DATE,1,length(put(b.REP_DATE,rep_clid_fmt)) 
    ; 
Quit; 

祝你好运!