SAS哈希表:是否有方法查找/连接不同的键或具有可选键

SAS哈希表:是否有方法查找/连接不同的键或具有可选键,sas,hashtable,Sas,Hashtable,我经常处理一些键不完美的数据,我需要连接来自不同来源的数据,我想继续使用哈希对象以获得速度优势,但是当我使用大量数据时,我可能会遇到崩溃(内存限制) 一个简单的概述是,我有两个不同的键,它们都是唯一的,但不是每个记录都有,我们将它们称为Key1和Key2 我目前的解决方案不是很优雅(但很有效),它是执行以下操作: if _N_ = 1 then do; declare hash h1(Dataset:"DataSet1"); h1.Def

我经常处理一些键不完美的数据,我需要连接来自不同来源的数据,我想继续使用哈希对象以获得速度优势,但是当我使用大量数据时,我可能会遇到崩溃(内存限制)

一个简单的概述是,我有两个不同的键,它们都是唯一的,但不是每个记录都有,我们将它们称为Key1和Key2

我目前的解决方案不是很优雅(但很有效),它是执行以下操作:

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;
所以我在两个哈希表中有完全相同的数据集,但是定义了两个不同的键,如果找不到第一个键,那么我会尝试找到第二个键

有人知道一种方法可以使它更高效/更容易阅读/减少内存占用吗

道歉如果这看起来是完成任务的一个糟糕的方式,我绝对欢迎批评,这样我就可以学习了

提前感谢,


Adam.

我是散列表查找的大力支持者——它们帮助我在几分钟内完成了数亿次大规模的行连接,否则可能需要几个小时

你做这件事的方式还不错。如果发现自己的内存不足,首先要确定的是哈希表实际使用了多少内存

一旦您了解了它的使用量并有了一个基准,或者如果它因为内存不足而根本无法运行,您可以使用一些选项来查看它们如何提高内存使用率和性能

1。仅包括所需的密钥和数据

加载哈希表时,排除任何不必要的变量。您可以在加载哈希表之前或加载过程中执行此操作。您可以使用数据集选项来帮助减少表的大小,例如
where
keep
drop

dcl散列h1(数据集:“mydata(keep=key var1)”

2。减少可变长度

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

%压缩(mydata,mydata_较小)

3。调整hashexp选项

hashexp
hashexp
的较大值将增加内存使用,但可能会提高性能。较小的值将减少内存使用。我建议你阅读上面的链接,同时也看看sasnrd在这篇文章顶部的链接,了解它将如何影响你的加入。此值的大小应根据表的大小适当调整。对于你应该使用什么价值,没有一个明确的答案,我的建议是你的系统所能处理的最大值

dcl散列h1(数据集:“mydata”,hashexp:2)

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

如果哈希表经常内存不足,则可能是
memsize
太低。如今许多机器都有大量的RAM,SAS在处理多个严重的SAS会话方面做得非常出色,即使在装备适度的机器上也是如此。增加此值可能会产生巨大的差异,但您希望调整此值作为最后手段

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

临时将其设置为0是一个有用的疑难解答工具,可以查看哈希对象在未运行时实际占用的内存量。但是如果这是你自己的机器,而你是唯一一个使用它的人,你可以直接把它设置为0


memsize
可以在SAS调用时进行调整,也可以直接在SAS中进行调整(9.4上的sasv9.cfg,或Viya中的sasv9_选项环境变量)。

我遇到了一个非常类似的问题,但处理方法略有不同

第一:不管是什么问题,斯图所说的一切都应该牢记在心

如果无法真正减小字符变量的大小(请记住,无论数据集大小如何,所有数字在RAM中都是8字节,因此不要因此而试图缩小它们),可以这样处理

  • 构建一个哈希表,其中key1作为键,key2作为数据以及实际数据。确保key1是“更好”的键-填充更充分的键。将Key2重命名为其他变量名,以确保不会覆盖真正的Key2
  • 按键1搜索。如果找到键1,那太好了!继续
  • 如果缺少key1,则使用hiter对象(散列迭代器)迭代搜索key2的所有记录
  • 如果经常使用key2,这不是很有效。第3步也可以用不同于使用击球员的方式来做得更好——例如,你可以为那些记录做一个键控集或其他事情。在我的特殊情况下,表和查找都缺少key1,因此可以简单地迭代更小的缺少key1的子集-如果在您的情况下这不是真的,并且您的主表已为两个键完全填充,那么这将要慢得多

    另一件事情是放弃哈希表,使用一个键集,或者一个格式,或者其他不使用RAM的东西。 或拆分数据集:

    data haskey1 nokey1;
      set yourdata;
      if missing(key1) then output nokey1;
      else output haskey1;
    run;
    
    然后是两个数据步骤,一个是带有key1的散列,另一个是带有key2的散列,然后将这两个步骤组合在一起


    其中哪一个最有效很大程度上取决于您的数据集大小(主数据集和查找数据集)以及键1的丢失情况。

    它有效吗?如果没有,你能解释一下它是如何失败的吗?你有多少内存?什么时候被记录