微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SAS哈希表:是否可以在不同的键上查找/联接或具有可选键

如何解决SAS哈希表:是否可以在不同的键上查找/联接或具有可选键

我经常处理一些键不完美的数据,并且需要从其他来源连接数据,我想继续使用哈希对象以提高速度,但是当我使用大量数据时,我可以遇到崩溃(内存限制)。

一个简化的概述是,我有2个不同的键,它们都是唯一的,但对于每条记录都不存在,我们将它们称为键1和键2。

我当前的解决方案虽然不是很优雅(但是可以用),但是它可以执行以下操作:

if _N_ = 1 then do;
   declare hash h1(Dataset:"DataSet1");
                h1.DefineKey("key1");
                h1.DefineData("Value");
                h1.DefineDone();
   declare hash h2(Dataset:"DataSet1");
                h2.DefineKey("key2");
                h2.DefineData("Value");
                h2.DefineDone();
end;

set DataSet2;

rc = h1.find();
if rc NE 0 then do;
    rc = h2.find();
end;

所以我在两个哈希表中具有完全相同的数据集,但是定义了2个不同的键,如果找不到第一个键,那么我尝试查找第二个键。

有没有人知道一种使这种方法更有效/更容易读取/减少内存密集型的方法

抱歉,如果这似乎是完成任务的一种不好方法,我绝对欢迎批评,让我可以学习!

预先感谢

亚当。

解决方法

我非常支持哈希表查找-它们帮助我在几分钟之内完成了数亿行的大规模连接操作,否则可能要花费数小时。

您的操作方式并不坏。如果您发现自己的内存不足,那么首先要确定的是哈希表实际使用了多少内存。 This article by sasnrd shows exactly how to do this

一旦您弄清了它的使用量并有一个基准,或者如果它由于内存不足而根本无法运行,则可以尝试一些选项,以查看它们如何改善内存使用率和性能。

1。仅包含您需要的密钥和数据

在加载哈希表时,请排除所有不必要的变量。您可以在加载哈希表之前或期间执行此操作。您可以使用数据集选项来帮助减小表的大小,例如wherekeepdrop

dcl hash h1(dataset: 'mydata(keep=key var1)');

2。减少可变长度

长字符变量占用更多内存。将长度减小到最小所需值将有助于减少内存使用量。使用%squeeze()宏可在加载之前自动将所有变量减小到所需的最小大小。您可以找到该宏here

%squeeze(mydata,mydata_smaller);

3。调整hashexp选项

hashexp helps improve performance and reduce hash collisionshashexp的较大值将增加内存使用量,但可能会提高性能。较小的值将减少内存使用量。我建议阅读上面的链接,并查看sasnrd在此文章顶部的链接,以了解它如何影响您的加入。该值的大小应根据表的大小进行适当调整。对于应该使用什么值,没有一个确定的答案,我的建议是您的系统可以处理的。

dcl hash h1(dataset: 'mydata',hashexp:2);

4。为您的SAS会话分配更多内存

如果您的哈希表经常用光内存,则memsize的值可能太低。如今,许多机器都有大量的RAM,即使在设备适中的机器上,SAS也可以很好地处理多个很难完成的SAS会话。增大此值可能会产生巨大的变化,但是您要调整此值作为最后的选择。

默认的memsize选项为2GB。尝试将其增加到4GB,8GB,16GB等,但是不要过度使用,例如将其设置为0以使用所需的内存。您不希望SAS会话占用机器上的所有内存,如果其他用户也在其中。

暂时将其设置为0可能是一个有用的故障排除工具,它可以查看哈希对象未运行时实际占用的内存量。但是,如果它是您自己的计算机,并且您是唯一使用它的计算机,则可以将其设置为0。

memsize可以在SAS调用时或在SAS Configuration File中直接调整(在9.4上为sasv9.cfg,在Viya中为SASV9_Option环境变量)。

,

我有一个非常相似的问题,我的处理方法略有不同。

首先:无论问题如何,都应牢记Stu所说的所有内容。

如果您处在无法真正减小字符变量大小的情况下(请记住,无论数据集大小如何,RAM中的所有数字均为8字节,因此请勿尝试缩小它们) ,您可以通过这种方式进行处理。

  1. 使用key1作为键,key2作为数据以及您的实际数据构建一个哈希表。确保key1是“更好的”键-填充更充分的键。重命名Key2为其他变量名称,以确保您不会覆盖实际的key2。
  2. 搜索key1。如果找到key1,那就太好了!继续前进。
  3. 如果key1丢失,则使用一个击打对象(哈希迭代器)遍历搜索key2的所有记录。

如果经常使用key2,这不是很有效。第3步也可能比使用击打手更好,例如,您可以对这些记录进行键设置或其他操作。在我的特殊情况下,表和查找都缺少key1,因此可以简单地遍历缺少key1的小得多的子集-如果在这种情况下,这是不正确的,并且主表中完全填充了两个键,则这会慢很多。

我要考虑的另一件事是放弃哈希表并使用键集,格式或其他不使用RAM的东西。

或拆分您的数据集:

data haskey1 nokey1;
  set yourdata;
  if missing(key1) then output nokey1;
  else output haskey1;
run;

然后是两个数据步骤,一个是带有key1的哈希值,另一个是带有key2的哈希值,然后将两者组合在一起。

其中哪种效率最高,很大程度上取决于您的数据集大小(主数据集和查找数据)以及key1的缺失。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。