大型数据集的PROC SQL更新效率
我有一个SAS主数据集,有1000万行和1800列。我需要使用具有1500万条记录的事务数据集更新10列,仅针对具有匹配键的记录。 我尝试使用以下代码运行proc sql update语句大型数据集的PROC SQL更新效率,sql,performance,sas,large-data,Sql,Performance,Sas,Large Data,我有一个SAS主数据集,有1000万行和1800列。我需要使用具有1500万条记录的事务数据集更新10列,仅针对具有匹配键的记录。 我尝试使用以下代码运行proc sql update语句 proc sql; UPDATE lib1.master1 a SET col1 = (SELECT col1 FROM lib1.changes_1 b WHERE a.key=b.key), col2 = (SELECT col2 FROM lib1.changes_1 b WHERE a.ke
proc sql;
UPDATE lib1.master1 a
SET col1 = (SELECT col1 FROM lib1.changes_1 b WHERE a.key=b.key),
col2 = (SELECT col2 FROM lib1.changes_1 b WHERE a.key=b.key),
col3 = (SELECT col3 FROM lib1.changes_1 b WHERE a.key=b.key),
col4 = (SELECT col4 FROM lib1.changes_1 b WHERE a.key=b.key),
col5 = (SELECT col5 FROM lib1.changes_1 b WHERE a.key=b.key),
col6 = (SELECT col6 FROM lib1.changes_1 b WHERE a.key=b.key),
col7 = (SELECT col7 FROM lib1.changes_1 b WHERE a.key=b.key),
col8 = (SELECT col8 FROM lib1.changes_1 b WHERE a.key=b.key),
col9 = (SELECT col9 FROM lib1.changes_1 b WHERE a.key=b.key)
WHERE EXISTS ( SELECT 1 FROM lib1.changes_1 b WHERE A.key = B.key);
quit;
为了测试,我尝试了col1,它已经运行了4个多小时
我可以考虑数据合并,方法是删除10列,然后左连接,但这会改变列的顺序。重新排列1800列将再次成为一项乏味的任务
有没有更快/更有效的技术?您面临一个挑战。首先,我建议在
lib1.changes\u 1(key)
上创建一个索引,如果您没有索引的话。这可能会大大提高性能
proc-sql
不支持更新中的join
——这正是您真正需要的。然而,许多底层数据引擎确实如此。因此,如果您正在与数据库中的数据(如MySQL、Postgres或SQL Server)通信,那么您可以编写一个本机模式查询,使用join
进行更新
全SAS解决方案是使用数据步骤。您面临一个挑战。首先,我建议在
lib1.changes\u 1(key)
上创建一个索引,如果您没有索引的话。这可能会大大提高性能
proc-sql
不支持更新中的join
——这正是您真正需要的。然而,许多底层数据引擎确实如此。因此,如果您正在与数据库中的数据(如MySQL、Postgres或SQL Server)通信,那么您可以编写一个本机模式查询,使用join
进行更新
全SAS解决方案是使用数据步骤。如何为事务数据集中的10列中的每列生成格式 生成虚拟数据集:
主数据集(10M记录)和事务数据集(15M记录):
(原始的事务
数据集在下面标准化,以准备创建每个事务变量的格式)
以格式读入:
proc format cntlin=transaction ;
run ;
data want ;
set master ;
col1=put(key,COL1F.) ;
col2=put(key,COL2F.) ;
col3=put(key,COL3F.) ;
col4=put(key,COL4F.) ;
col5=put(key,COL5F.) ;
col6=put(key,COL6F.) ;
col7=put(key,COL7F.) ;
col8=put(key,COL8F.) ;
col9=put(key,COL9F.) ;
col10=put(key,COL10F.) ;
output ;
run ;
然后将格式应用于主数据集:
proc format cntlin=transaction ;
run ;
data want ;
set master ;
col1=put(key,COL1F.) ;
col2=put(key,COL2F.) ;
col3=put(key,COL3F.) ;
col4=put(key,COL4F.) ;
col5=put(key,COL5F.) ;
col6=put(key,COL6F.) ;
col7=put(key,COL7F.) ;
col8=put(key,COL8F.) ;
col9=put(key,COL9F.) ;
col10=put(key,COL10F.) ;
output ;
run ;
如何为事务数据集中的10列中的每一列生成格式 生成虚拟数据集:
主数据集(10M记录)和事务数据集(15M记录):
(原始的事务
数据集在下面标准化,以准备创建每个事务变量的格式)
以格式读入:
proc format cntlin=transaction ;
run ;
data want ;
set master ;
col1=put(key,COL1F.) ;
col2=put(key,COL2F.) ;
col3=put(key,COL3F.) ;
col4=put(key,COL4F.) ;
col5=put(key,COL5F.) ;
col6=put(key,COL6F.) ;
col7=put(key,COL7F.) ;
col8=put(key,COL8F.) ;
col9=put(key,COL9F.) ;
col10=put(key,COL10F.) ;
output ;
run ;
然后将格式应用于主数据集:
proc format cntlin=transaction ;
run ;
data want ;
set master ;
col1=put(key,COL1F.) ;
col2=put(key,COL2F.) ;
col3=put(key,COL3F.) ;
col4=put(key,COL4F.) ;
col5=put(key,COL5F.) ;
col6=put(key,COL6F.) ;
col7=put(key,COL7F.) ;
col8=put(key,COL8F.) ;
col9=put(key,COL9F.) ;
col10=put(key,COL10F.) ;
output ;
run ;
总结
lib1。将\u 1
更改为临时表(例如,lib1。更改\u 1\u rolledup
),执行完全扫描。(lib1.changes\u rolledup
的物理属性应该仔细设置。)lib1更新lib1.master1
。更改rolledup
的数据,执行其中一个的完全扫描和另一个的索引扫描。(哪一个要完全扫描取决于实际数据。)lib1.changes\u 1(key)
值都与lib1.master1(key)
值中的一个匹配(lib1.changes\u 1
甚至可能是lib1.master1
的详细表)。此外,我们还需要应用lib1.changes\u 1
中的所有更改。这意味着我们必须从lib1.changes\u 1
读取所有记录。如果是这样,最有效的方法是执行lib1.changes\u 1
表完整扫描,但只执行一次。此完整扫描将汇总来自lib1的所有更改。更改\u 1
为此类定义的(可能的临时)表:
-- pseudo code:
create [temporary] table lib1.changes_1_rolledup
<set physical attributes depending on your data nature - see below>
as select key, col1, col2, col3, col4, col5, col6, col7, col8, col9
from lib1.changes_1
where 1 = 2
总结
lib1。将\u 1
更改为临时表(例如,lib1。更改\u 1\u rolledup
),执行完全扫描。(lib1.changes\u rolledup
的物理属性应该仔细设置。)lib1更新lib1.master1
。更改rolledup
的数据,执行其中一个的完全扫描和另一个的索引扫描。(哪一个要完全扫描取决于实际数据。)lib1.changes\u 1(key)
值都与lib1.master1(key)
值中的一个匹配(lib1.changes\u 1
甚至可能是lib1.master1
的详细表)。此外,我们还需要应用lib1.changes\u 1
中的所有更改。这意味着我们必须从lib1.changes\u 1
读取所有记录。如果是这样,最有效的方法是执行lib1.changes\u 1
表完整扫描,但只执行一次。此完整扫描将汇总来自lib1的所有更改。更改\u 1
为此类定义的(可能的临时)表:
-- pseudo code:
create [temporary] table lib1.changes_1_rolledup
<set physical attributes depending on your data nature - see below>
as select key, col1, col2, col3, col4, col5, col6, col7, col8, col9
from lib1.changes_1
where 1 = 2
要替换一列,格式(大致类似于Bendy的方法)是最简单的 要替换始终来自同一行的十列,我建议使用哈希表。通常与单一格式的速度相同。(在10MM行标记处,格式实际上可能有点慢,因此这可能比一行更快。) 这在我的笔记本电脑上花费了约30秒的时间(CPU时间和实时;我有一个SSD,所以它们类似。在HDD上,这可能是30秒的CPU时间和几分钟的实时时间。)
要替换一列,格式(大致类似于Bendy的方法)是最简单的。