考虑以下(诚然很长)的例子。
示例代码创建两个数据集,数据一个带有“关键”变量i,j,k,数据二带有关键变量j,k和一个“值”变量x。我想尽可能有效地合并这两个数据集。两个数据集都是针对j和k编制索引的:不应该需要第一个数据的索引,但它仍然存在。
Proc SQL不使用数据二中的索引,如果数据位于关系数据库中,我认为就是这种情况。这只是我必须接受的查询优化器的限制吗?
编辑:这个问题的答案是肯定的,SAS可以使用索引来优化PROC SQL连接。在下面的示例中,数据集的相对大小很重要:如果修改代码以使数据2变得比数据1大,则将使用index。无论数据集是否排序,都无关紧要。
* Just to control the size of the data;
%let j_max=10000;
* Create data sets;
data one;
do i=1 to 3;
do j=1 to &j_max;
do k=1 to 4;
if ranuni(0)<0.9 then output;
end;
end;
end;
run;
data two;
do j=1 to &j_max;
do k=1 to 4;
x=ranuni(0);
if ranuni(0)<0.9 then output;
end;
end;
run;
* Create indices;
proc datasets library=work nolist;
modify one;
index create idx_j_k=(j k);
modify two;
index create idx_j_k=(j k) / unique;
run;quit;
* Test the use of an index for the other data set:
* Log should display "INFO: Index idx_j_k selected for WHERE clause optimization.";
options msglevel=i;
data _null_;
set two(where=(j<100));
run;
* Merge the data sets with proc sql - no index is used;
proc sql;
create table onetwo as
select
one.*,
two.x
from one, two
where
one.j=two.j and
one.k=two.k;
quit;
答案 0 :(得分:6)
您可能正在比较苹果和橘子。对于使用proc sql
进行的连接,索引可能没有帮助,因为观察已经按j和k排序,并且有更快的方法来进行“合并”而不是使用索引。
对于data _null_
步骤的子集化,另一方面,j
上的索引肯定会有所帮助。如果您使用proc sql
执行相同的子集,则会看到 使用索引。
proc sql;
select * from two where j < 100;
quit;
/* on log
INFO: Index idx_j_k selected for WHERE clause optimization.
*/
顺便说一句,您可以使用未记录的_method
选项来检查proc sql
执行查询的方式。在Windows上的sas 9.2上,它报告它正在执行所谓的“散列连接”:
proc sql _method;
create table onetwo as
select
one.*,
two.x
from one, two
where
one.j=two.j and
one.k=two.k;
quit;
/* on log
NOTE: SQL execution methods chosen are:
sqxcrta
sqxjhsh
sqxsrc( WORK.ONE )
sqxsrc( WORK.TWO )
*/
有关详细信息,请参阅Paul Kent的Tech note。