背景
存储在基于MS-SQL的服务器上的原始数据集(每天更改):Sourcelib.RAW
和LOCAL
excel文件(保留unchanged
)。
我需要刷新位于WANT
的数据集Targerlib
。目前我有SQL代码在2-3分钟内执行此类任务。但我想知道SAS是否可以做同样的事情,而处理时间不会增加太多。
work.IMP
约为6M记录,每条记录约50个字节。CANNOT
一次建立,然后每天向其添加新数据。因为以前的数据可能(甚至非常不可能)发生变化。 根据@Joe,我应该允许在proc compare
中使用update
或data step
更新目标文件。这是我发布的相关问题How to use proc compare to update dataset
"compatible"
时)过程
subset&tranpose
导入work.IMP
。由于某些原因,此文件只能以这种方式创建。它CANNOT
存储在服务器中。 work.IMP
和一个原始数据集Sourcelib.RAW1
执行外部联接以获取work.HAVE1
。请注意,work.IMP
已排序,但Sourcelib.RAW1
未排序。外连接仅用于(有一些标准)确定每个数据记录。 i.e. case when a.COL1 is '' then b.COL1 else a.COL1 end as COL1
您可以认为此过程是使用Sourcelib.RAW1
调整work.IMP
。
PS1:@sparc_spread建议直接向服务器执行导入过程。但它在LOCAL
中没有任何好处。此处的hash object
也无济于事。
Sourcelib.RAW2
配置为work.temp
,然后将sort
配置为work.HAVE2
。 (Sourcelib.RAW2
中的数据大部分都没有按顺序排列。)work.HAVE1
连接work.HAVE2
,proc append
(因为两个表都很大)是work.HAVE
PS2:step3
中的排序是为了避免在step4
结束时进行排序。实际上,数据Targerlib.WANT
不一定是有序的。但最好这样做。
work.HAVE
复制到服务器Targetlib.HAVE
。 我在WORK
做了大部分事情,这只花了我几分钟。但step5
可能需要半个小时才能完成复制。
根据@Joe,这可能主要是由于与网络传输有关的事情。 I.E
最小化网络传输
问题
有什么方法可以改善step5
?或者对整个过程进行任何修改都会改善性能?
答案 0 :(得分:1)
一些想法。
首先,假设这是一个SAS数据集而不是SQL数据库或其他东西,options compress=binary;
是一个好主意,假设这主要是数字(如果没有,则为options compress=character;
)。在大多数情况下,要么会显着减小数据集的物理尺寸。
其次,300MB在事物计划中并不是很多。我的网络会在不到一分钟的时间内写出来。您的网络条件可能会推动您做出的其他一些选择;例如,如果单个慢点就是简单地在其上复制数据,那么你需要弄清楚如何以你做任何其他事情为代价来减少数据。
假设您没有更改任何其他内容,我建议您将have1
直接写为网络have
,然后将have2
添加到网络中。 IE,无论创建have1
的步骤,都可以直接写入网络。这包括sort
步骤,请注意:因此,如果您创建它,则对其进行排序,在本地创建并使用out=
网络库对其进行排序。这样可以减少写入的总量(因为您没有将have1
的无用副本写入本地驱动器)。这有助于在本地写作是整个过程的相关成本,但如果它几乎完全是网络拥塞则无济于事。
使用操作系统副本复制文件几乎总是优于任何其他复制方法,因此如果网络拥塞是您唯一关心的因素,您可能希望在本地创建(在WORK或本地但常量目录中,比如C:\temp\
或类似的),然后让您的流程的最后一步执行copy c:\temp\have.sas7bdat \\networklocation\whereitgoes\
。这通常会优于SAS方法,因为它可以利用有效的技术。
PROC COPY
是解决网络拥塞的另一种选择;它可能比PROC APPEND
快(如果本地写出可以忽略不计,就像我对<1 GB数据那样),并且具有在运输过程中发生某些事情时更安全的优点。 (附加也应该没问题,但是你知道COPY肯定没有改变昨天的文件。)
最后,您可能想要找出一些方法来允许更新目标文件。在大多数情况下,这并不是那么难。一个例子是保留昨天文件的副本,对今天的文件执行PROC COMPARE
,然后在更新文件中包含每个更改的记录(无论更改是什么)。然后从目标文件中删除任何匹配的旧记录并附加新记录。相对于通过网络发送的总记录而言,这是非常快的,因此如果网络拥塞是主要问题,则可以节省大量时间(但需要更多的CPU时间来进行PROC COMPARE)。
答案 1 :(得分:0)
您可以使用PROC APPEND
有效地创建新数据集,而不仅仅是附加到现有数据集 - 因此您可以使用它基本上将步骤3和4合并到此中:
/* To fulfill requirement 4, delete existing Targetlib.HAVE */
PROC DELETE LIBRARY="Targetlib" DATA="HAVE";
RUN;
/* Targetlib.HAVE does not yet exist, the first APPEND will create it */
PROC APPEND BASE="Targetlib.HAVE" DATA="work.HAVE1";
RUN;
PROC APPEND BASE="Targetlib.HAVE" DATA="work.HAVE2";
RUN;
这应该至少节省一些时间,但这仍然无法解决你所有的问题......我在问题的评论中还有一些额外的问题,并且会尽可能地根据它们改变这个答案
以下是一种在一步中执行左连接和连接的方法,并立即将结果写入targetlib
。我无法保证这会更快,但值得一试。我使用key
和val
作为字段名称,根据您的需要进行替换。
PROC SQL _METHOD;
CREATE TABLE targetlib.HAVE
AS
SELECT
a.key ,
CASE WHEN MISSING (a.val) THEN b.val ELSE a.val END AS val
FROM
Sourcelib.RAW1 AS a
LEFT JOIN
IMP AS b
ON
a.key = b.key
UNION
SELECT
c.*
FROM
Sourcelib.RAW2 AS c
ORDER BY
key
;
QUIT;
RUN;
_METHOD
是一个记录稀疏的SAS功能,将打印查询计划,请参阅this link。这可能会给你更多的见解。另外,我假设已经从Excel导入了IMP
,并且它位于WORK
中。尝试查看是否将其导入targetlib
并将IMP as b
替换为targetlib.IMP as b
更快。
由于您使用的是Windows,请在数据集名称后尝试数据选项SGIO=YES
:例如: Sourcelib.RAW1 AS a
变为Sourcelib.RAW1 (SGIO=YES) AS a
。有关Windows SGIO和SAS的详细信息,请参阅this link和this older but more comprehensive one。
可能更高效的方法是避免连接并改为使用哈希对象:哈希对象can be found here和a good tip sheet is here的良好文档。目前尚不清楚这是否会更快 - imp
有6米的记录,但每个记录50个字节,大约300 MB,这适合你的RAM。具有那么多条目的哈希表的性能很大程度上取决于SAS的哈希算法。无论如何,这是使用哈希对象的代码。在其中,我们假设在IMP
数据集中,val
字段已重命名为val2
。
DATA targetlib.HAVE (DROP = rc val2);
LENGTH val2 8. ;
IF (_N_ = 1) THEN DO;
DECLARE HASH h (DATASET: "IMP") ;
h.DEFINEKEY ('key');
h.DEFINEDATA ('val2');
h.DEFINEDONE ();
END;
SET
sourcelib.RAW1
sourcelib.RAW2
;
IF MISSING (val) THEN DO;
rc = h.find();
IF (rc = 0) THEN DO;
val = val2;
END;
END;
RUN;
PROC SORT DATA = targetlib.HAVE ; BY KEY ; RUN ;
尝试一下,看看它是否更快。再一次,使用IMP
等来试验SGIO
的位置。最后PROC SORT
可能很贵;如果您之前排序的唯一原因是因为加入,那么跳过它。
通常,您使用SAS的方法应该是尽可能少的I / O,并找到将多个操作组合到PROC
或DATA
步骤的单个写入中的方法。