我是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
。除了将其完全关闭(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;
在第二个查询的情况下,它可能会拉低所有tableA。在第四个查询中,它很可能会将where子句传递给服务器(假设日期不会造成问题,但是应该不会,SAS知道如何将日期转换为oracle类型的日期)。
请注意,SAS处理程序也可以生成直通。PROC MEANS等将把指令发送给Oracle以执行均值/总和/等。如果可以轻松做到这一点。
最好的选择是:
归根结底,无论您做什么,都会受到网络流量的限制。尽力将其最佳化。听起来您已经了解了如何执行此操作,因此只需执行通常在非SAS环境中执行的操作即可。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句