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

时间:2015-10-20 15:25:35

标签: sas

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

因此,我们应该始终将字符变量的长度指定为8的倍数。

我搜索过,找不到对初始断言的任何支持。

这是真的吗?这是否包含在文档中的某处?

3 个答案:

答案 0 :(得分:2)

对于不包含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行)。这不是因为为字符变量保存了任何特定大小,而是因为数据记录的总长度。

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

答案 1 :(得分:1)

对于包含数字变量的数据集,如同@ 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 - 如果数字变量长度不长,则表示没有缓冲区。 twelve_six_eight的概念长度为26,物理尺寸为32:18,最多为24,最后为8。 (你可以通过简单地添加几个6字节的数字来验证它是不是为每个数字变量分配8;它们从不增加总填充,并且整齐地适合较小的空间。)

以下是它最终的结果:

  • x $ 6
  • y $ 6
  • z 6
  • i 8

会像这样:

[00000000011111111112222222222333333333344444444445]
[12345678901234567890123456789012345678901234567890]
[xxxxxxyyyyyyzzzzzz      iiiiiiii]

一方面注意:我并非100%确定它不是[iiiiiiiixxxxxxyyyyyyzzzz]。这样就可以预测数值变量的位置。但它并没有真正影响到这一点:无论如何,如果你有一个或多个8字节,如果你的非8字节数字存储总量不是8字节的倍数,那么会有一个小缓冲区数字变量。

答案 2 :(得分:0)

正如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

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

我尝试对 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

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