Proc SQL: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,但我认为这并不重要。)通常,我必须首先将一个表上载到我的个人模式,该模式定义了我们要检查的客户机的数量。其他一切都在服务器上。有时我会将它们的查询折叠在一起,因为它们可以在一个步骤中完成,但我不相信这就是为什么我的程序版本要快得多的原因 我认为procsql会上传初始数据集,然后在服务器上运行第一个查询。然后将输出下载到本地计算机,创建本地SAS数据集。对于第二个procsql步骤,它将在第一步中创建的表上载回服务器,然后在服务器上运行查询。更糟糕的是,“本地”SAS数据集实际上存储在远程服务器上,而不是实际的本地机器上。这对SAS来说是不可见的,但它确实意味着我们再次通过网络复制数据。我认为SAS运行缓慢,因为存在大量不必要的网络流量 问题#1-我对proc sql的理解正确吗?我们真的在浪费我认为我们在网络上上传和下载大型表/数据集的时间吗 Qeustion#2-是否有某种方法可以控制proc sql何时针对服务器运行,何时针对本地数据库运行?在某些情况下,如果我们能够阻止上传/下载步骤,查询将运行得更高效。Short-response 你的理解并不完全正确,但大致正确。SQL可能没有将SAS数据集发送到服务器,它更可能将服务器数据下载到SAS,但它可能正在下载整个表,而不受连接条件的限制。你的解决方案正是我所建议的——希望你的同事也能加入Proc SQL:SAS如何/何时移动数据,sas,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表。他们没有使用passth
长话短说 就处理工作方式而言,这取决于您的代码
PROC SQL
将在本地执行代码(如中,在SAS服务器/桌面上),除非它决定将查询传递到服务器,并且没有被告知不允许这样做。这称为隐式传递
。除了完全关闭它(使用PROC SQL
语句上的noipassthru
),您无法真正控制它。有时可以使用options msglevel=i
(一个系统选项)和\u方法
或\u树
查看SQL决定做什么(类似于解释计划)
我曾经遇到过这样的情况:SQL Server不敏感地运行字符比较,而SAS不敏感地运行字符比较,我有一个特定的查询,有时发送到服务器,有时不依赖于数据的详细信息。我在检查用例时不够仔细,所以当它确实不正确时(比较Propcase和UPCASE),它似乎可以工作
一般规则是,在以下情况下,SAS将尝试将查询发送到服务器:
- 查询中的数据已完全驻留在服务器上
- 查询非常简单,SAS可以很容易地找出如何用其本机语言告诉服务器进行查询
libname或lib-oracle[连接信息];
proc-sql;
*有可能通过;
选择tableA.*,tableB.cost
从oralib.tableA内部连接oralib.tableB
表A.id=表B.id;
*可能不会通过;
选择tableA.*,tableB.cost
从oralib.tableA内部联接work.tableB
表A.id=表B.id;
*可能通过,也可能不通过;
选择tableA.*、tableB.cost、tableC.productID
从oralib.tableA内部连接oralib.tableB
在tableA.id=tableB.id上
左连接oralib.tableC
表a.id=表c.id;
*这会下载数据,但可能会应用where语句服务器端;
选择tableA.*,tableB.cost
从oralib.tableA内部联接work.tableB
在tableA.id=tableB.id上
其中表A.date<'2010年1月1日'd;
退出
在第二个查询的情况下,它可能会将所有tableA都拉下来。在第四个查询中,它可能会将where子句传递给服务器(假设日期不会引起问题,但不应该,SAS知道如何将日期转换为oracle类型的日期)
请注意,SAS进程还可以生成直通。PROC MEANS等将向Oracle发送指令,以便执行MEANS/sums等操作(如果可以轻松执行)
您的最佳选择是:
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;