Oracle:是否可以计算table中数据实际使用的存储大小?

Oracle: is it possible to calculate actual storage size used by the data in a table?

我希望能够报告 table 中的数据所使用的实际存储量,这样我就可以删除 n。行数据(作为数据删除工作的一部分),然后我可以重新分析 table 存储量以计算已通过数据删除释放的实际存储量。

我正在使用以下查询,但我意识到这可能会将 分配的 存储 space 返回给各个 table 段,而不是数据消耗的实际存储space:

SELECT 
     OWNER "SCHEMA"
    ,SEGMENT_NAME 
    ,SUM(BYTES) "TOTAL BYTES"
    ,SUM(BYTES/1024) "TOTAL KB (BINARY)"
    ,SUM((BYTES/1024)/1024) "TOTAL MB (BINARY)"
    ,ROUND(SUM(((BYTES/1024)/1024)/1024),6) "TOTAL GB (BINARY)" 
FROM dba_segments
WHERE 
    SEGMENT_TYPE = 'TABLE'
GROUP BY 
     OWNER
    ,SEGMENT_NAME
ORDER BY 
     OWNER 
    ,ROUND (SUM(((BYTES/1024)/1024)/1024),6) desc

Oracle Database Concepts 文档确实很有用,但是通读了其他一些可用于各种静态数据字典视图的文档后,我并不能马上明白 where/what 是最好的基础进行我需要的计算。

例如,如果我从 DBA_TABLES 视图中的 'BLOCKS' 字段中获取统计数据,并将其乘以我们分配的块大小(即 8 字节),就是给我分配的或 table?

的实际数据量

您可能想要基于 dbms_space.space_usage procedure 的内容。这将告诉您有多少块是 0-25% 满、25-50% 满、50-75% 满、75-100% 满以及完全满。我在下面的脚本中使用了中点估计——如果你想确定你将通过删除大量数据。您还需要 运行 对任何索引、物化视图等执行相同的过程,这些操作会受到从 table.

中删除数据的影响。
drop table foo;
/

create table foo (
  col1 number
);

insert into foo
  select level 
    from dual
 connect by level <= 10000;
 
declare
  l_unformatted_blocks integer;
  l_unformatted_bytes integer;
  l_fs1_blocks integer;
  l_fs1_bytes integer;
  l_fs2_blocks integer;
  l_fs2_bytes integer;
  l_fs3_blocks integer;
  l_fs3_bytes integer;
  l_fs4_blocks integer;
  l_fs4_bytes integer;
  l_full_blocks integer;
  l_full_bytes integer;
  l_partition_name varchar2(30) := null;
  l_segment_size integer;
begin
  select sum(bytes)
    into l_segment_size
    from user_segments
   where segment_name = 'FOO';

  dbms_space.space_usage( user, 'FOO', 'TABLE',
                          l_unformatted_blocks, l_unformatted_bytes,
                          l_fs1_blocks, l_fs1_bytes,
                          l_fs2_blocks, l_fs2_bytes,
                          l_fs3_blocks, l_fs3_bytes,
                          l_fs4_blocks, l_fs4_bytes,
                          l_full_blocks, l_full_bytes,
                          l_partition_name );
  dbms_output.put_line( 'Segment size is ' || l_segment_size || 
                        ' of which roughly ' || 
                        to_char( 
                          l_full_bytes + 
                          l_fs4_bytes * 0.125 + 
                          l_fs3_bytes * 0.375 + 
                          l_fs2_bytes * 0.625 +
                          l_fs1_bytes * 0.875
                        ) ||
                        ' bytes used ' ||
                        to_char( 
                          8 * 1024 *
                          l_full_blocks + 
                          l_fs4_blocks * 0.125 + 
                          l_fs3_blocks * 0.375 + 
                          l_fs2_blocks * 0.625 +
                          l_fs1_blocks * 0.875
                        ) ||
                        ' if we use blocks.' 
);
end;
/