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

机会

我是DBA / R用户。我只是在一个充满SAS用户的办公室里工作,我试图更好地了解SAS的proc sql的工作方式。我知道SAS包括一个关系数据库,并且它具有对Oracle等外部服务器运行proc sql的能力。我试图更好地理解何时/如何决定使用数据库服务器而不是其内部数据库系统。

我已经看到一些非常慢的SAS代码,我的同事在其中运行一系列proc sql命令。这些程序通常包括3-5个proc sql步骤。每个proc sql命令都会创建一个本地SAS表。他们没有使用直通SQL。数据集很大(一百万行以上),这些proc sql步骤运行缓慢。大多数数据保存在服务器上。通常有一个小表定义了我们要查看的填充,它位于SAS数据文件中,但其他所有内容都位于服务器上。

通过直接在服务器上直接运行所有查询,我已经展示了速度的显着提高。(在这种情况下是Oracle,但我认为这并不重要。)通常,我必须首先将一个表上载到我的个人模式中,该表定义了我们要检查的客户群。其他所有内容都在服务器上。有时我可以将它们的查询折叠在一起,因为它们可以在一个步骤中完成,但是我不认为这就是为什么我的程序版本如此之快的原因。

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

问题#1-我对proc sql所做的理解是否正确?我们是否真的浪费了我认为要在网络上上传和下载大型表/数据集的时间?

问题2-有什么方法可以控制proc sql何时对服务器运行以及何时对本地数据库运行?在某些情况下,如果我们可以阻止上载/下载步骤,则查询将更有效地运行。

简短答案

您的理解并不完全正确,但这是正确的选择。SQL可能没有将SAS数据集发送到服务器,而是更有可能将服务器数据下载到SAS-但它可能正在下载整个表,不受联接条件的限制。您的解决方案正是我建议的解决方法-希望您的同事加入。


长答案

在处理方式方面,这取决于您的代码。PROC SQL将在本地执行代码(例如,在SAS服务器/台式机上),除非它决定将查询传递给服务器并且没有被告知不允许这样做。叫做implicit passthrough除了将其完全关闭(noipassthruPROC 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处理程序也可以生成直通。PROC MEANS等将把指令发送给Oracle以执行均值/总和/等。如果可以轻松做到这一点。

最好的选择是:

  1. 尽一切可能做所有有意义的事情。确保直通服务器的唯一方法是使用直通。
  2. 如果服务器上有一个大表,而SAS中有一个小表,则将SAS中的表上载到服务器。直通会话和libname会话无法看到彼此特定于会话的临时表,因此您必须使用GTT或类似的东西(所有用户都可以看到的东西)。同样,如果您在SAS中有一个大表,而在SQL中有一个小表(或小的查询结果),请在本地将其关闭(必要时通过传递)。
  3. 当您必须放倒东西时,请尽可能地限制。当我在这种环境中工作时,仅通过加入服务器上的表来限制我的结果集,然后再降低它们,就可以节省大量时间。

归根结底,无论您做什么,都会受到网络流量的限制。尽力将其最佳化。听起来您已经了解了如何执行此操作,因此只需执行通常在非SAS环境中执行的操作即可。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章