我是DBA/R用户.我刚刚在一个充满SAS用户的办公室找到了一份工作,我正在努力更好地理解SAS的proc sql是如何工作的.我知道SAS包含一个关系数据库,它包括对Oracle等外部服务器运行proc sql的能力.我试图更好地了解它何时/如何决定使用数据库服务器而不是其内部数据库系统.
我见过一些非常慢的SLOW SAS代码,我的同事运行一系列proc sql命令.这些程序通常包括3-5个proc sql步骤.每个proc sql命令都会创建一个本地SAS表.他们没有使用passthrough sql.数据集很大(100万行+),这些proc sql步骤运行缓慢.大多数数据都存在于服务器上.通常有一个小表来定义我们想要查看的填充,它位于SAS数据文件中,但其他所有内容都存在于服务器上.
通过直接在服务器上运行所有查询,我已经证明了速度的显着提高.(在这种情况下是Oracle,但我认为这不重要.)通常,我必须首先将一个表上传到我的个人模式,该模式定义了我们想要检查的客户群.其他一切都在服务器上.有时我会将他们的查询合并在一起,因为它们可以在一个步骤中完成,但我不相信这就是为什么我的程序版本更快.
我认为proc sql上传了初始数据集,然后在服务器上运行第一个查询.然后,它将输出下载到本地计算机,创建本地SAS数据集.对于第二个proc sql步骤,它将在步骤1中创建的表上载回服务器,然后在服务器上运行查询.更糟糕的是,"本地"SAS数据集实际上存储在远程服务器上,而不是实际的本地机器上.这对SAS来说是不可见的,但它确实意味着我们再次在网络上复制数据.我认为SAS由于大量不必要的网络流量而运行缓慢.
问题#1 - 我对proc sql的正确理解是什么?我们是否真的在浪费尽可能多的时间,因为我认为我们正在通过网络上传和下载大型表格/数据集?
Qeustion#2 - 是否有某种方法可以控制proc sql针对服务器运行的时间与针对本地数据库运行的时间?在某些情况下,如果我们可以阻止上传/下载步骤,查询将更有效地运行.
你的理解并不完全正确,但它是在正确的球场.SQL可能没有将SAS数据集发送到服务器,更有可能将服务器数据下载到SAS - 但它可能正在下载整个表,而不受连接标准的限制.您的解决方案正是我建议您做的 - 希望您的同事能够加入.
就处理的工作方式而言,这取决于您的代码. PROC SQL将在本地执行代码(如在SAS服务器/桌面上),除非它决定将查询传递给服务器并且没有被告知它不被允许.这就是所谓的implicit passthrough.你不能真正控制它,除非完全关闭它(noipassthru在PROC SQL声明中).您可以使用options msglevel=i;(系统选项)查看它,_METHOD或者_TREE查看SQL决定做什么(类似于解释计划).
我遇到过它造成伤害的情况:SQL Server运行字符比较不区分大小写,而SAS则没有,我有一个特定的查询,有时发送到服务器,有时不依赖于数据的细节.我对检查案例不够谨慎,所以当它真的不正确时它似乎工作(比较Propcase和UPCASE).
一般规则是,如果出现以下情况,SAS将尝试将查询发送到服务器:
如果您正在使用本地SAS数据集运行查询(例如,在本地将服务器表连接到SAS数据集),则不会(至少据我所知)去服务器.它应该始终在本地运行,这意味着从服务器下载贡献表中的所有数据(如果查询中有逻辑过滤器,可能会过滤).IE(这些示例不一定是好的SQL代码,只是概念的例子):
libname oralib oracle [connection info];
proc sql;
*Will pass through likely;
select tableA.*, tableB.cost
from oralib.tableA inner join oralib.tableB
on tableA.id=tableB.id;
*Will probably not pass through;
select tableA.*, tableB.cost
from oralib.tableA inner join work.tableB
on tableA.id=tableB.id;
*Might pass through, might not;
select tableA.*, tableB.cost, tableC.productID
from oralib.tableA inner join oralib.tableB
on tableA.id=tableB.id
left join oralib.tableC
on tableA.id=tableC.id;
*This downloads the data but probably applies the where statement server side;
select tableA.*, tableB.cost
from oralib.tableA inner join work.tableB
on tableA.id=tableB.id
where tableA.date < '01JAN2010'd;
quit;
Run Code Online (Sandbox Code Playgroud)
在第二个查询的情况下,它可能会将所有tableA拉下来.在第四个查询中,它可能会将where子句传递给服务器(假设日期不会导致问题,但它不应该,SAS知道如何将日期转换为oracle类型日期).
请注意,SAS触发器也可以生成passthrough.PROC MEANS等会将指令发送给Oracle以执行手段/总和/等.如果它可以很容易地这样做.
你最好的选择是:
在一天结束时,无论你做什么,你都会受到网络流量的限制; 尽量优化它.听起来你已经明白了如何做到这一点,所以只要做你在非SAS环境中通常会做的事情.