oracle数据库高水位线问题处理

1、什么是高水线(High Water Mark)?数据库

Oracle 数据库在建立一张表时,会为这张表分配一个段空间(segment),为了方便理解,把段空间容纳数据的上限,称之为高水位线(HIGH WATER MARK) HWM ,HWM是一个标记,用来讲明表示有多少未使用的块分配给这个段。
两个结论:
1.水位线以上表示已经分配但还未使用块(block),水位先如下爱表示已经分配且已经使用过的块(包含了正在使用的块和使用过的且被删除了数据的空块)
2.理论上来讲,一张表的水位线只会增大不会减少(除非经过特殊的方法重置),即便将表中的数据所有删除,HWM仍是为原值。oracle

2、HWM数据库的操做有以下影响:app

a) 全表扫描一般要读出直到HWM标记的全部的属于该表数据库块,即便该表中没有任何数据。spa

b) 即便HWM如下有空闲的数据库块,键入在插入数据时使用了append关键字,HWM也会不断增大,占用系统资源,表所占的实际空间会不断增大,致使系统出现问题索引

3、高水位线缘由以及解决方法:资源

产生缘由:
1.操做表时使用删除了大量数据。
2.在插入时使用了/append nologging/语句,append关键字会从为表分配段中的随机位置插入,水位线会不断增高。
3.Sql load 时默认使用truncate 自带了reuse storage参数,致使truncate之后水位线不会下降。同步

解决方法:
1.直接truncate table drop storage
2.创建一张维护表按期move并重建索引或者shrink space。
3.表数据落表时按照日期创建了备份表,保留必定天数数据
4.Rename表名,重建表,重建索引,将数据导入重建表,drop原表,而后rename重建表为原表
5.使用alter table 表名 shrink space(oracle10新增功能)
6.在线表重定义(功能强大,操做复杂,通常不使用,能够改变表的结构)
表重建的两个方法move与shrink的对比:
move是oracle8出现的命令,使用时会建立一块和原来表空间相同大小的另外一块表空间,而后进行数据的复制,完成后使用后表替换原表,解决hwm的问题。
缺点:操做时锁表,索引会失效。
shrink是oracle10新增功能,使用时不会开辟新的表空间,操做分为两步,第一步整理数据,第二步下降水位线,进行第一步时,能够在线进行操做。能够再业务不繁忙的时候进行第二步操做。
缺点:相比move速度比较缓慢。
shrink的详细操做步骤:
详细收缩步骤it

  1. 全表收缩
    无论分区表仍是非分区表,收缩均可以表级别进行,具体语句以下:
    ALTER TABLE owner.table_name ENABLE ROW MOVEMENT;(开启行移动会使游标失效,需谨慎)
    ALTER TABLE owner.table_name SHRINK SPACE COMPACT CASCADE(第一步整理数据,并不会下降高水位线,能够在线进行操做);
    ALTER TABLE owner.table_name SHRINK SPACE CASCADE(第二步分析重置高水位线,会短暂锁表须要在业务量小的时候进行操做);io

  2. 单个分区收缩
    分区表的收缩还能够分区级别进行,具体语句以下:
    ALTER TABLE owner.table_name ENABLE ROW MOVEMENT;
    ALTER TABLE owner.table_name MODIFY PARTITION partition_name SHRINK SPACE COMPACT CASCADE;
    ALTER TABLE owner.table_name MODIFY PARTITION partition_name SHRINK SPACE CASCADE;
    ALTER INDEX owner.index_name MODIFY PARTITION partition_name SHRINK SPACE COMPACT CASCADE;
    ALTER INDEX owner.index_name MODIFY PARTITION partition_name SHRINK SPACE CASCADE;table

4、在线表重定义步骤:

一、确认表是否能够作在线重定义:
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE(
uname => 'OWNER',
tname => 'ORIGTABLENAME',
options_flag => dbms_redefinition.cons_use_pk);
END;
/
--若是有主键则是options_flag => DBMS_REDEFINITION.cons_use_pk,若是没有DBMS_REDEFINITION.cons_use_rowid

二、建立新的中间表TABLENAME_TMP准备重定义 (能够新增删除字段、能够修改表存储参数、能够修改成分区表等须要的操做)
注意由于在线重定义过程当中要求列的属性要相同,所以不可以使用dbms_redefinition完成列类型的调整

--普通表
CREATE TABLE OWNER.TABLENAME_TMP ( ) TABLESPACE XXX;
--分区表
CREATE TABLE OWNER.TABLENAME_TMP ( )
PARTITION BY RANGE (PARTITIONNAME)
(
PARTITION P1 VALUES LESS THAN ('xxx'),
...
PARTITION PMAX VALUES LESS THAN (MAXVALUE)
)
TABLESPACE XXX;

三、开启并行提升在线重定义速度:
ALTER SESSION FORCE PARALLEL DML PARALLEL 2;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 2;

四、开始在线重定义:
BEGIN
dbms_redefinition.start_redef_table(
uname => 'OWNER',
orig_table => 'ORIGTABLENAME',
int_table => 'TABLENAME_TMP',
options_flag => dbms_redefinition.cons_use_pk);
END;
/
--若是有主键则是options_flag => DBMS_REDEFINITION.cons_use_pk,若是没有DBMS_REDEFINITION.cons_use_rowid

五、使用COPY_TABLE_DEPENDENTS把原始表的权限、约束、索引等在中间表上建立一份
DECLARE
num_errors PLS_INTEGER;
BEGIN
dbms_redefinition.copy_table_dependents(
uname => 'OWNER',
orig_table => 'ORIGTABLENAME',
int_table => 'TABLENAME_TMP',
copy_indexes => dbms_redefinition.cons_orig_params,
copy_triggers => true,
copy_constraints => true,
copy_privileges => true,
ignore_errors => false,
num_errors => num_errors,
copy_statistics => true);
END;
/

六、假如在线重定义要好久,这期间应用往源表插入数据,中间表并不会有这条数据,使用sync_interim_table包同步在线重定义期间源表全部的DML的数据:
BEGIN
dbms_redefinition.sync_interim_table(
uname => 'OWNER',
orig_table => 'ORIGTABLENAME',
int_table => 'TABLENAME_TMP');
END;
/

七、完成在线重定义:
BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE(
uname => 'OWNER',
orig_table => 'ORIGTABLENAME',
int_table => 'TABLENAME_TMP');
END;
/

九、中间重定义报错时须要执行如下命令终止重定义:
*BEGIN
*DBMS_REDEFINITION.ABORT_REDEF_TABLE(
*uname => 'OWNER',
*orig_table => 'ORIGTABLENAME',
*int_table => 'TABLENAME_TMP');
*END;
*/

十、肯定数据索引等同步成功后,删除中间表: drop table OWNER.TABLENAME_TMP;