SYS@orcl 25-SEP-14>create table t1 as select * from dba_objects where 1=2;
Table created.
然后再查询oracle为这张表分配了多大的空间:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 8
随着业务的增长我们会往这张表里插入大量的数据,高水位线就是一个段内的标记,用来说明还有多少没使用的块可以分配给这个segment。通常情况下,高水位线的增长幅度是一次5个数据块。原则上高水位线只能增大不能缩小,即使将表中的数据全部delete掉,高水位线还是会保持原来的位置,因为这样,所以即使我们将表中的大部分数据删除了,在进行查询操作的时候还是会进行全段扫描,全表扫描通常要读出直到高水位线标记的所有的属于该表的数据块,这样会大大降低查询性能。另外当我们往表中插入记录的时候,使用的是高水位线以上的数据块,此时高水位线又会增长。SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 8
以下是处理高水位线的方法:
1.将表进行重建,使用语句alter table table_name move tablespace tablespace_name;
注意,使用了这个语句之后,原表上的索引也会无效,因此执行完以上语句之后要对表中的索引进行重建。
2.执行alter table table_name shrink space;
这是oracle10g引入的新性能,注意,在执行这条语句之前,先要允许行移动,alter table table_name enable row movement;
move是通过移动数据来降低hwm,需要更多的磁盘空间,而shrink是通过delete和insert,会产生较多的undo和redo。
move的效率相对于shrink来说要高一些,但是会导致索引失效。
3.重建表
复制要保留的数据到临时表t_tmp,drop原表,然后rename临时表t_tmp为原表,注意重建过程需要备份该表的触发器和存储过程等语法。
4.逻辑导入导出
5.alter table table_name deallocate unused;
deallocate unused会hwm上面未使用的空间,但是并不会释放hwm下面的自由空间,也不会移动hwm的位置。
6.truncate table
下面我们以第一种方式move为例看看如何处理高水位线:
刚刚我们创建了一张表结构和dba_objects一样的表t1,现在做如下相关查询:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 8
往表中插入足够多的数据:
SYS@orcl 25-SEP-14>insert /*+ APPEND NOLOGGING */ into t1 select * from dba_objects;
72602 rows created.
SYS@orcl 25-SEP-14>commit;
Commit complete.
SYS@orcl 25-SEP-14>select max(object_id) from t1;
MAX(OBJECT_ID)
--------------
75306
SYS@orcl 25-SEP-14>insert /*+ APPEND NOLOGGING */ into t1 select
2 owner,object_name,subobject_name,object_id+75306,data_object_id,object_type,created,last_ddl_time,timestamp,status,temporary,generated,secondary,
3 namespace,edition_name from t1;
72602 rows created.
SYS@orcl 25-SEP-14>commit;
Commit complete.
SYS@orcl 25-SEP-14>create unique index idx_objectid on t1(object_id) tablespace users;
Index created.
SYS@orcl 25-SEP-14>create index idx_index02 on t1(owner,object_name) tablespace users;
Index created.
查看索引信息:
SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';
INDEX_NAME STATUS
------------------------------ --------
IDX_INDEX02 VALID
IDX_OBJECTID VALID
再次查看表的信息:SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';
INDEX_NAME STATUS
------------------------------ --------
IDX_INDEX02 VALID
IDX_OBJECTID VALID
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 2176
SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1
可以看到这里的记录为空,这是因为没有做统计分析:
SYS@orcl 25-SEP-14>exec dbms_stats.gather_table_stats(user,'T1');
PL/SQL procedure successfully completed.
SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1 145204 2068 0
这里看到empty_blocks的信息仍为空,这是因为这个字段只有通过analyze收集统计信息之后才会有数据:
SYS@orcl 25-SEP-14>analyze table t1 compute statistics;
Table analyzed.
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1 145204 2068 107
SYS@orcl 25-SEP-14>select 2068 + 107 from dual;
2068+107
----------
2175
(这里和前面的2176相比少了一个块,那一个块是用来存储segment信息的)
下面我们delete表中的数据,留下两行:
SYS@orcl 25-SEP-14>delete from t1 where rownum<=145202;
145202 rows deleted.
SYS@orcl 25-SEP-14>select count(*) from t1;
COUNT(*)
----------
2
再次查看表信息:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 2176
SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1 145204 2068 107
可以看出高水位线并没有发生任何变化。下面使用move来处理高水位线:
SYS@orcl 25-SEP-14>alter table t1 move tablespace hh;
Table altered.
查看索引状态已变为unusable,重建索引:
SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';
INDEX_NAME STATUS
------------------------------ --------
IDX_INDEX02 UNUSABLE
IDX_OBJECTID UNUSABLE
SYS@orcl 25-SEP-14>alter index IDX_INDEX02 rebuild;
Index altered.
SYS@orcl 25-SEP-14>alter index IDX_OBJECTID rebuild;
Index altered.
SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';
INDEX_NAME STATUS
------------------------------ --------
IDX_INDEX02 VALID
IDX_OBJECTID VALID
重新进行统计分析,查看表信息:
Table analyzed.
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1 TABLE 8
SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1 2 4 4
说明此时高水位线已经降低了。