我在Oracle 11g Standard One Edition中有一个表:
表1
col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 col11
1 NULL 2 3 4 5 NULL NULL 19 21 22
1 NULL 2 3 4 5 NULL 1 Jan 2009 19 21 22
1 NULL 2 3 4 5 NULL NULL 19 21 22
1 9 2 3 4 5 A NULL 19 21 22
1 NULL 2 3 4 5 B NULL 19 21 22
表格desc是:
Name Null Type
-------------------- ---- -------------
COL1 NUMBER
COL2 NUMBER
COL3 NUMBER
COL4 NUMBER
COL5 NUMBER
COL6 NUMBER
COL7 VARCHAR2(255)
COL8 DATE
COL9 DATE
COL10 DATE
COL11 VARCHAR2(255)
我需要找出表消耗的存储百分比是多少?
示例:使用的table1存储空间为1 GB,其中的NULL消耗100MB,因此,NULL占用存储空间的10%。
另外,ORACLE中是否有NULL的替代表示?
答案 0 :(得分:25)
表中的NULL可能只占存储空间的1.75%。
但是这个数字毫无意义,即使它是基于下面可重复的测试用例。理解NULL很小(只有一个字节)更重要。真实的"真实的"除极端情况外,尺寸应无关紧要。如此微小,以至于担心替代表现几乎总是浪费时间。
最佳案例测试案例(实践中的空间使用)
让我们使用您的表定义创建1GB的数据。首先,让我们创建表格。
create table test1(
COL1 NUMBER,
COL2 NUMBER,
COL3 NUMBER,
COL4 NUMBER,
COL5 NUMBER,
COL6 NUMBER,
COL7 VARCHAR2(255),
COL8 DATE,
COL9 DATE,
COL10 DATE,
COL11 VARCHAR2(255)
) pctfree 0 /* Let's assume no updates or deletes, and pack the data tightly */;
现在创建一千兆字节的数据。每个值都使用该数据类型的最大可能值。
begin
for i in 1 .. 15 loop --Magic number to generate exactly 1GB.
insert into test1
select
.0123456789012345678901234567890123456789,
.0123456789012345678901234567890123456789,
.0123456789012345678901234567890123456789,
.0123456789012345678901234567890123456789,
.0123456789012345678901234567890123456789,
.0123456789012345678901234567890123456789,
lpad('A', 255, 'A'),
sysdate,
sysdate,
sysdate,
lpad('A', 255, 'A')
from dual
connect by level <= 95000; --Magic number to generate exactly 1GB.
commit;
end loop;
end;
/
这些查询显示它为1,425,000行使用1GB空间。
select count(*) from test1;
select bytes/1024/1024/1024 gb from user_segments where segment_name = 'TEST1';
现在创建第二个表,其行数相同,但每列中都有NULL
。
create table test1_null as
select col1+null c1, col2+null c2, col3+null c3, col4+null c4, col5+null c5, col6+null c6,
cast(null as varchar2(255)) c7, col8+null c8, col9+null c9, col10+null c10,
cast(null as varchar2(255)) c11
from test1;
新细分大小仅为0.0175GB,即1.75%。
select bytes/1024/1024/1024 gb from user_segments where segment_name = 'TEST1_NULL';
为什么测试用例具有误导性
虽然这可能听起来像一个简单的问题,但完全回答它需要整本书或水晶球。获得真正的存储大小非常复杂。你至少需要考虑这些问题:
PCTFREE
之类的设置,是否删除了以前的行,上次重组表的时间,块大小等。< / LI>
行的格式(理论上的空间使用)
以下图片来自Logical Storage Structures chapter of the Concepts Guide:
列数据由一系列列长度和列值组成。如果值为NULL,则“列长度”设置为0,“列值”不使用任何空格。这就是为什么NULL总是只使用1个字节,数字为0。
大多数数据类型都是可变的,因此长度至少使用1个字节,如果非NULL,则该值至少使用1个字节。静态数据类型(如DATE
)仍将使用1个字节作为长度,然后使用7个字节作为值。同样,除非日期为NULL,否则长度设置为0,值为空。
此图像也可以解释&#34;尾随NULL&#34;存储技巧。当有尾随空值时,Oracle可能会将列数设置为较低,将最后一列长度保留为0,并推断其余列也为NULL。
替代陈述?
现在我开始怀疑了。询问NULL的替代表示会让人联想到四种人:
是的,NULL有点奇怪。但它很快就会有意义。不要过多担心空间,或者完全避免使用NULL的方法。您为NULL支付的价格与您为完全避免它们的反模式支付的价格相比毫无价值。
答案 1 :(得分:2)
首先取决于表属性(分区,索引,数据类型,lob字段等),文件系统和其他一些因素。 在过去,我有一个类似的任务oracle 11.以下是我采取的步骤(因为大小不需要非常精确 - 数据库有超过3000个表):
我的算法
计算每列的空值(这可以自动执行,以便检查哪些列的空值更高)
SELECT COUNT(*)FROM YourTable WHERE YourColumn IS NULL
仅根据最后一次测量(1000条记录)创建副本;
分析结果。
希望他会帮助你。注意:至少在我的情况下,目标是分析数据库使用情况并进行清理。
关于这个主题的一些读物: