我听说SAS将字符变量存储在8个字节的块中。
因此,我们应该始终将字符变量的长度指定为8的倍数。
我搜索过,找不到对初始断言的任何支持。
这是真的吗?这是否包含在文档中的某处?
答案 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;它们从不增加总填充,并且整齐地适合较小的空间。)
以下是它最终的结果:
会像这样:
[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的倍数。