示例:
create table sample-name
{
sample-col-name number(1);
}
如果我们看到上面的例子。创建表时,将创建sample-col-name列。默认情况下,它占用22个字节,因为它包含数字数据类型。但是oracle动态地为我们插入的值提供内存。假设我们输入1值,则只给出1个字节。 我的问题是保留了22个字节?那么,如果从22个字节中分配1个字节,那么其他21个字节是否未被使用?
谢谢。
答案 0 :(得分:2)
您似乎在询问数字值是否消耗了22个字节的存储空间,即使它并不需要所有这些字节来存储它。 A non-zero single-digit number requires two bytes of storage.,并且正如文档所说,它们以可变长度格式存储。
如果消耗了所有22个字节,那么对于您存储的每个数字,将浪费20个字节。
您可以测试是否发生了这种情况。
create table t42 (n number(1));
column data_type format a10
select data_type, data_length from user_tab_columns where table_name = 'T42';
DATA_TYPE DATA_LENGTH
---------- -----------
NUMBER 22
该表最初没有分配存储空间(延迟段创建),但只要添加一行就会分配一个段;在这个例子中是64k:
select extents, bytes from user_segments where segment_name = 'T42';
no rows selected
insert into t42 select 1 from dual;
1 row inserted.
select extents, blocks, bytes from user_segments where segment_name = 'T42';
EXTENTS BLOCKS BYTES
---------- ---------- ----------
1 8 65536
您可以使用vsize
或dump
查看该值所需的存储空间,如链接答案中所述:
select n, vsize(n), dump(n) from t42;
N VSIZE(N) DUMP(N)
---------- ---------- --------------------
1 2 Typ=2 Len=2: 193,2
如果表有32768(32k)行,每行有相同的单个数字值,那么它需要65536(64k)的存储,每个两个字节,或720896( 704k)存储,每个22字节。仅针对该列没有任何行开销(至少 3 bytes per row)或块开销(每块约84-107字节)。
insert into t42 select 1 from dual connect by level < 3300;
3,299 rows inserted.
N COUNT(*) SUM(VSIZE(N))
---------- ---------- -------------
1 3300 6600
select extents, blocks, bytes from user_segments where segment_name = 'T42';
EXTENTS BLOCKS BYTES
---------- ---------- ----------
1 8 65536
所有3300行仍然适合单个64k范围。如果他们实际上每个数字使用22个字节,那么那些已经需要72500个字节,并且必须已经添加另一个范围。
我没有随机选择3300行;在我的系统上,还有一行确实让我进入了第二个范围:
insert into t42 select 1 from dual;
1 row inserted.
select n, count(*), sum(vsize(n)) from t42 group by n;
N COUNT(*) SUM(VSIZE(N))
---------- ---------- -------------
1 3301 6602
select extents, blocks, bytes from user_segments where segment_name = 'T42';
EXTENTS BLOCKS BYTES
---------- ---------- ----------
2 16 131072
因此涉及到相当多的块和行开销。您可以了解具有更多列的表的多少:
drop table t42;
create table t42 (n1 number, n2 number, n3 number, n4 number, n5 number);
insert into t42 select 1, 2, 3, 4, 5 from dual connect by level <= 1815;
select count(*), sum(vsize(n1) + vsize(n1) + vsize(n1) + vsize(n1) + vsize(n1)) as total_vsize from t42;
COUNT(*) TOTAL_VSIZE
---------- -----------
1815 18150
select extents, blocks, bytes from user_segments where segment_name = 'T42';
EXTENTS BLOCKS BYTES
---------- ---------- ----------
1 8 65536
再次添加一行需要第二个范围。但是现在如果我们有1815行,每行有五个单数,那么如果每个行使用22个字节,我们需要199650个字节,显然我们实际上并没有使用它。正如您所期望的那样,与具有更多行的更多行的数量存储相比,行开销不太重要。但在这个仍然有人工作的例子中,我们仍然只能在64k范围内获得大约18k的实际数据;比单个列只有6k的早期示例更好......
自行尝试使用您的配置和更多列,和/或具有不同数据类型的列(varchar2
的行为方式类似)。