8的倍数- SAS字符变量的最佳长度

  • 本文关键字:最佳 字符变量 SAS sas
  • 更新时间 :
  • 英文 :


我听说SAS将字符变量存储在8字节的块中。

因此,我们的想法是,我们应该总是将字符变量的长度赋值为8的倍数。

我已经搜索过了,找不到任何支持最初断言的证据。

是真的吗?这在文档中有涉及吗?

对于不包含8字节数值变量的数据集是正确的。我将单独发布的数据集。


不,8字节字符可变长度没有什么特别的。

见下文:

data length8;
  length char0001-char9999 $8;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;
data length7;
  length char0001-char9999 $7;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;
data length4;
  length char0001-char9999 $4;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;
data length12;
  length char0001-char9999 $12;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;
data length16;
  length char0001-char9999 $16;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;
data length17;
  length char0001-char9999 $17;
  call missing(of _all_);
  do _i = 1 to 100; 
    output;
  end;
  drop _i;
run;

这些数据集的大小不同,大致与字符变量的长度成正比。请注意,4的大小按比例要大一些(无论如何,在我的机器上):实际上,4、5、6都是相同的大小。这是因为页面大小的原因:在我的安装中,最小的页面大小是64kb(65535字节),而4、5、6都只能容纳一行数据(大约40、50和60kb行)。这并不是因为为字符变量保存了任何特定的大小,而是因为数据记录的总长度。

这就是您可以通过更改少量来节省的地方:如果您的数据碰巧被安排为页面大小刚好是行大小的两倍,那么使行稍微小一点将节省一半的空间。这种情况不太可能发生,除非在极少数情况下-它需要非常宽的行(许多变量,或非常长的字符变量)。不过,您也可以使用选项更改页面大小,这可能是处理此类边缘情况的更好方法。

对于包含数字变量的数据集,如@jaamor的示例所包含的,存在与8字节大小相关的存储有一些影响的差异。它通常不会对数据集大小产生重大影响,除非在非常高和窄的数据集上,但对于 非常高和窄的数据集,这可能是一个考虑因素。

当一个长度为8字节(默认值)的数字变量时,SAS将这些数字变量放在数据向量的末尾,并以8字节的倍数开始,可能是为了帮助访问这些可预测的数字变量的效率。除8字节数字之外的任何其他变量将被放置在数据向量的开头,然后添加任何填充以使其达到8字节的倍数,然后将8字节数字变量放置在其后。

这可以通过查看一些示例数据集的proc contents输出来看出。

data fourteen_eight;
  length x y $7;  *14 total;
  length i 8;
run;
data twelve_eight;
  length x y $6;  *12 total;
  length i 8;
run;
data twelve_six;
  length x y $6;  *12 total;
  length i 6;
run;
data twelve_six_eight;
  length x y $6;
  length z 6;
  length i 8;
run;

fourteen_eight的概念观测长度为22,但物理观测长度为24(以PROC CONTENTS为例)。twelve_eight的概念长度为20,但物理观测长度也为24。twelve_six的概念长度为18,物理观察长度为18——这意味着如果数值变量不是8长,则没有缓冲区。twelve_six_eight的概念长度为26,物理大小为32:18四舍五入为24,最后是8。(您可以通过简单地添加几个6字节的数字来验证它不是为每个数字变量分配8;它们从不增加总内边距,并且能很好地适应较小的空间。

结果如下:

    <
  • x 6美元/gh><
  • y 6美元/gh>z 6
  • 我8

应该是这样的:

[00000000011111111112222222222333333333344444444445]
[12345678901234567890123456789012345678901234567890]
[xxxxxxyyyyyyzzzzzz      iiiiiiii]

旁注:我不能100%确定它不是[iiiiiixxxxxxyyyyyyzzzz]。这就像预测数值变量的位置一样有效。但是,这并不会真正影响到这一点:无论哪种方式,如果您的非8字节数字存储总量不是8字节的倍数,如果您确实有一个或多个8字节数字变量,则会有一个小缓冲区。

正如Joe所说,我使用以下脚本进行了经验测试:

libname testlen "<directory>";
%macro create_ds(length=, dsName=);
    data &dsName;
        length x $&length.;
        do i=1 to 1000000;
            x="";
            output;
        end;
    run;
%mend;
%macro create_all_ds;
    %do i=1 %to 20;
        %create_ds(length=&i, dsName=testlen.len&i)
    %end;
%mend;
%create_all_ds

所有数据集都有一个变量。变量的长度因数据集而异,从1到20不等。

数据集1-8占用约15.8 MB

数据集9-16占用~23.7 MB

数据集16-20占用约31.5 MB

这可能意味着对于1个变量数据集,声明不是8 的倍数的SAS变量长度是不节省空间的。

我对2个变量数据集:

进行了类似的测试
 %macro create_ds(length=, dsName=);
    data &dsName;
        length x y $&length.;
        do i=1 to 1000000;
            x="";
            y="";
            output;
        end;
    run;
%mend;
%macro create_all_ds;
    %do i=1 %to 20;
        %create_ds(length=&i, dsName=testlen.len&i)
    %end;
%mend;
%create_all_ds

结果如下:

数据集1-4占用约15.8 MB

数据集5-8占用约23.7 MB

这可能意味着对于有效的长度声明,字符变量长度的应该是8的倍数。

最新更新