SAS Proc SQL 不存在查询与数据步骤 a=1 b=0

SAS Proc SQL Not Exist Query vs Data Step a=1 b=0

尝试测量两个小数据集的性能,以便为一对更大的数据集确定有效的执行方法。

*这个测试是在一个有 32 个观测值的数据集和一个有 37 个观测值的数据集上进行的。

两种方法都给我相同的结果,处理时间略有不同。我有一个简单的数据步骤:

data check;
merge d1(in=a) d2(in=b);
by ssn;
if a=0 and b=1;
run;

Data Step 方法(第一次执行)日志生成以下内容 -

NOTE: There were 32 observations read from the data set WORK.D1.
NOTE: There were 37 observations read from the data set WORK.D2.
NOTE: The data set WORK.CHECK has 5 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds

Proc SQL 方法(在我们的特定情况下不存在查询)在下面-

proc sql;
create table chck2 as
select b.* from d2 b
where not exists (select a.* from d1 a
                  where a.ssn=b.ssn)
;
quit;

sql 过程在日志中打印以下内容 -

NOTE: PROCEDURE SQL used (Total process time):
      real time           0.04 seconds
      cpu time            0.03 seconds

这些方法都产生相同的结果,创建了相同 5 个人的最终数据集。虽然数据步处理看起来更快(即使只有几分之一秒),但这些性能结果是否始终成立?数据步骤方法总是会赢吗?这里的关键影响因素是什么?按特定顺序列出 table 会起作用,还是 SAS 会同时扫描两个 table?

仅供参考 - 我提到(第一次执行)是因为我从上面的实验和一般曝光中注意到,如果您随后处理数据步骤,SAS 将比原始执行更快地处理后续步骤。假设这与 SAS 对先前执行的步骤有记忆有关...?

您永远不会从小型数据集中找到有意义的性能评估。开销将不可避免地影响任何类型的实际性能差异。 PROC SQL 在调用过程中有一些开销(百分之几秒),这比总执行时间还多。 运行 您的测试具有足够大的数据集,需要几分钟才能完成 运行 - 通常这是测试耗时过长和合法差异被 overhead/randomness 压缩之间的正确平衡。

至于什么会更快:如果数据集是排序的,并且 SAS 知道它是排序的,那么两个进程将在相同的时间量级内进行的可能性非常大。数据步骤合并非常快,SQL 合并也是如此。

如果未排序,SQL 可能(可能会)选择将 where-exists 转换为散列连接,这比对大型数据集排序要快得多。当然,这需要数据集适合内存。在数据步骤中排序然后合并可能与 SQL 相同,或者它可能更慢 - 甚至更快,但我怀疑如果需要先排序通常不会快很多。如果需要(哈希或格式),数据步骤中有比 sort/merge 更快的解决方案。

至于 PROC SQL 语句的顺序是什么;如果 SQL 可以弄清楚您在做什么并对其进行优化,则可能性不大。但是,它可能因为SQL可能不容易看到最优路径,所以一个命令(通常是大数据集为主,较小数据集为子查询)可能会有所帮助SQL 比其他人更容易找出正确的方法。

并且 - SAS 执行第二个或更晚时间的速度更快的原因 运行 是您的 OS(或者可能是您的文件系统)正在缓存读取,因此它没有从磁盘重新读取 SET 文件。