Proc SQL:SAS如何/何时移动数据

时间:2014-06-03 14:17:40

标签: sas

我是DBA / R用户。我刚刚在一个充满SAS用户的办公室找到了一份工作,我想更好地了解SAS' proc sql有效。据我所知,SAS包含一个关系数据库,它包括对Oracle等外部服务器运行proc sql的能力。我想更好地了解它何时/如何决定使用数据库服务器而不是内部数据库系统。

我见过一些真正的S. L. O. W. SAS代码,其中我的同事运行一系列proc sql命令。这些程序通常包括3-5个proc sql步骤。每个proc sql命令都会创建一个本地SAS表。他们没有使用passthrough sql。数据集很大(100万行+),这些proc sql步骤运行缓慢。大多数数据都存在于服务器上。通常会有一个小表来定义我们想要查看的填充,它位于SAS数据文件中,但其他所有内容都存在于服务器上。

通过直接在服务器上运行所有查询,我已经证明了速度的显着提高。 (在这种情况下是Oracle,但我不认为这很重要。)通常,我必须先将表上传到我的个人架构,该架构定义了我们要检查的客户群。其他一切都在服务器上。有时我会将他们的查询合并在一起,因为它们可以在一个步骤中完成,但我不相信这就是为什么我的程序版本更快的原因。

我认为proc sql上传了初始数据集,然后在服务器上运行第一个查询。然后,它将输出下载到本地计算机,创建本地SAS数据集。对于第二个proc sql步骤,它将在步骤1中创建的表上载回服务器,然后在服务器上运行查询。为了使这一切更加糟糕," local" SAS数据集实际存储在远程服务器上,而不是实际的本地计算机上。这对SAS来说是不可见的,但它确实意味着我们再次在网络上复制数据。我认为SAS由于大量不必要的网络流量而运行缓慢。

问题#1 - 我对proc sql的正确理解是什么?我们是否真的在浪费尽可能多的时间,因为我认为我们正在通过网络上传和下载大型表格/数据集?

Qeustion#2 - 是否有某种方法可以控制proc sql针对服务器运行的时间与针对本地数据库运行的时间?在某些情况下,如果我们可以阻止上传/下载步骤,查询将更有效地运行。

1 个答案:

答案 0 :(得分:8)

简短回答

你的理解并不完全正确,但它在正确的球场上。 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数据集运行查询(例如,将服务器表本地连接到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;

在第二个查询的情况下,它可能会将所有tableA拉下来。在第四个查询中,它可能会将where子句传递给服务器(假设日期不会导致问题,但它不应该,SAS知道如何将日期转换为oracle类型日期)。

请注意,SAS procs也可以生成passthrough。 PROC MEANS等会将指令发送给Oracle以执行手段/总和/等。如果它可以很容易地这样做。

你最好的选择是:

  1. 尝试尽可能地完成所有事情(这是有意义的)。确保它进入服务器的唯一方法是使用passthrough。
  2. 如果服务器上有一个大表,SAS中有一个小表,请将SAS中的表上传到服务器。直通会话和libname会话无法看到每个其他会话特定的临时表,因此您必须使用GTT或类似的(所有用户都可以看到)。同样,如果您在SAS中有一个大表,在SQL中有一个小表(或小查询结果),请在本地将其关闭(必要时通过passthrough)。
  3. 当你必须把事情搞砸时,尽可能地限制。当我在这种环境中工作时,我只需加入服务器上的表格就可以节省大量时间,以限制我的结果集。
  4. 在一天结束时,无论你做什么,都会受到网络流量的限制;尽量优化它。听起来你已经明白了如何做到这一点,所以只要做你在非SAS环境中通常会做的事情。