删除并截断和 table 大小

Delete and Truncate and table size

我尝试了此查询以了解删除和截断后对 table 大小的影响。

select * from SALES_HISTORY;
Output:
Product     Month       Sales
sony    22-DEC-17   24000
sony    22-DEC-17   24000
sony    22-DEC-17   24000
sony    22-DEC-17   24000
sony    22-DEC-17   24000
sony    22-DEC-17   24000

Delete from sales_history:
commit;

select segment_name,segment_type,bytes/1024/1024 MB
from dba_segments
where segment_type='TABLE' and segment_name='SALES_HISTORY';

Output:
segment_name    segment_type   MB
SALES_HISTORY   TABLE         0.0625

Truncate table SALES_HISTORY;

之后,我再次尝试查找 table 的大小,但似乎与下图相同。如果截断了所有行,它不应该为零吗?

Output:
segment_name    segment_type   MB
SALES_HISTORY   TABLE         0.0625

我需要了解删除和截断后对table和水印大小的影响。

如果您使用的是 11g R2 或更高版本,请查看 DROP ALL STORAGE 是否符合您的要求。看看下面的例子:

SQL> create table test_truncate as select level id, sysdate + level datum
  2  from dual connect by level <= 100000;

Table created.

SQL> select segment_name,segment_type,bytes/1024/1024 MB
  2  from dba_segments
  3  where segment_type='TABLE' and segment_name='TEST_TRUNCATE';

SEGMENT_NAME         SEGMENT_TYPE               MB
-------------------- ------------------ ----------
TEST_TRUNCATE        TABLE                       3

SQL> truncate table test_truncate;

Table truncated.

SQL> select segment_name,segment_type,bytes/1024/1024 MB
  2  from dba_segments
  3  where segment_type='TABLE' and segment_name='TEST_TRUNCATE';

SEGMENT_NAME         SEGMENT_TYPE               MB
-------------------- ------------------ ----------
TEST_TRUNCATE        TABLE                   ,0625

SQL> truncate table test_truncate DROP ALL STORAGE;

Table truncated.

SQL> select segment_name,segment_type,bytes/1024/1024 MB
  2  from dba_segments
  3  where segment_type='TABLE' and segment_name='TEST_TRUNCATE';

no rows selected

SQL>

truncate 有几个选项,下面是这些选项和 delete 如何影响存储和高水位线:

  • delete 将所有 space 分配给 table。高水位线保持不变
  • truncate table ... reuse storage 将所有 space 分配给 table。这会将高水位线重置为第一个范围
  • truncate table ... drop storage(默认值)为 table 释放 minextents 上方的所有 space。并因此重置高水位线
  • truncate table ... drop all storage 从 table
  • 释放所有 space

您可以使用 dbms_space.unused_space 来验证这一点:

create table t as 
  select level id, lpad ( 'x', 1000, 'x' ) stuff 
  from   dual
  connect by level <= 1000;

create or replace procedure show_size as

   out_total_blocks               integer;
   out_total_bytes                integer;
   out_unused_blocks              integer;
   out_unused_bytes               integer;
   out_last_used_extent_file_id   integer;
   out_last_used_extent_block_id  integer;
   out_last_used_block            integer;

begin

  dbms_space.unused_space(
    segment_owner              =>  user
    ,segment_name              =>  'T'
    ,segment_type              =>  'TABLE'
    ,total_blocks              =>  out_total_blocks
    ,total_bytes               =>  out_total_bytes 
    ,unused_blocks             =>  out_unused_blocks
    ,unused_bytes              =>  out_unused_bytes
    ,last_used_extent_file_id  =>  out_last_used_extent_file_id
    ,last_used_extent_block_id =>  out_last_used_extent_block_id
    ,last_used_block           =>  out_last_used_block
  );

  dbms_output.put_line ( 'Total Blocks:    ' ||  out_total_blocks || ' (blocks in the segment)');
  dbms_output.put_line ( 'Total Bytes:     ' ||  out_total_bytes || ' (segment size in bytes)');
  dbms_output.put_line ( 'Unused Blocks:   ' ||  out_unused_blocks || ' (empty blocks)');
  dbms_output.put_line ( 'Unused Bytes:    ' ||  out_unused_bytes || ' (size of empty space in bytes)');
  dbms_output.put_line ( 'Last Used Block: ' ||  out_last_used_block || ' (high water mark)');
end;
/ 

exec show_size;

Total Blocks:    256 (blocks in the segment)
Total Bytes:     2097152 (segment size in bytes)
Unused Blocks:   101 (empty blocks)
Unused Bytes:    827392 (size of empty space in bytes)
Last Used Block: 27 (high water mark)

delete t;
commit;

exec show_size;

Total Blocks:    256 (blocks in the segment)
Total Bytes:     2097152 (segment size in bytes)
Unused Blocks:   101 (empty blocks)
Unused Bytes:    827392 (size of empty space in bytes)
Last Used Block: 27 (high water mark)

truncate table t
  reuse storage;

exec show_size;

Total Blocks:    256 (blocks in the segment)
Total Bytes:     2097152 (segment size in bytes)
Unused Blocks:   253 (empty blocks)
Unused Bytes:    2072576 (size of empty space in bytes)
Last Used Block: 3 (high water mark)

truncate table t
  drop storage;

exec show_size;

Total Blocks:    8 (blocks in the segment)
Total Bytes:     65536 (segment size in bytes)
Unused Blocks:   5 (empty blocks)
Unused Bytes:    40960 (size of empty space in bytes)
Last Used Block: 3 (high water mark)

truncate table t
  drop all storage;

exec show_size;

Total Blocks:    0 (blocks in the segment)
Total Bytes:     0 (segment size in bytes)
Unused Blocks:   0 (empty blocks)
Unused Bytes:    0 (size of empty space in bytes)
Last Used Block: 0 (high water mark)

我想知道你没有包括 table 结构来计算大小。显示的大小是 table 的结构大小。

 Tables whole size= Tables structure 
 (Table name and fields (0.0625 mb)) + 
 (records/the 
  data (remaining size in mb)) as per the 
above data u showed

验证更改 table 并删除一个 column/field

  ALTER TABLE SALES_HISTORY DROP 
  Sales;

 select  
 segment_name,segment_type,
bytes/1024/1024 MB
from dba_segments
where segment_type='TABLE' and 
segment_name='SALES_HISTORY';