• 如何收缩表空间大小


    转摘:

    oracle数据库表空间文件收缩实例

    1.查看数据文件的使用情况

    包括内容:数据文件大小,已经used空间,free空间,hwm信息

     1 select /*+ ordered use_hash(a,b,c) */
     2 a.file_id,a.file_name,a.filesize, b.freesize,
     3 (a.filesize-b.freesize) usedsize,
     4  c.hwmsize,
     5  c.hwmsize - (a.filesize-b.freesize) unsedsize_belowhwm,
     6  a.filesize - c.hwmsize canshrinksize 
     7 from 
     8 (
     9 select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
    10 ) a,
    11 (
    12 select file_id,round(sum(dfs.bytes)/1024/1024) freesize from dba_free_space dfs
    13 group by file_id
    14 ) b,
    15 (
    16 select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
    17 group by file_id) c
    18 where a.file_id = b.file_id
    19   and a.file_id = c.file_id
    20 order by unsedsize_belowhwm desc
    查看数据文件使用情况

    结果说明:
    File_id : 文件编号
    File_name: 文件名称
    File_size: 数据文件占用磁盘空间大小
    Freesize:文件中被标记为free的空间大小
    Usedsize: 使用的空间大小。
    Hwmsize: 已经分配出去的空间大小,如果希望通过alter database datafile … resize integerM回收空间,将需要这个值作为参考,不能回收到这个值之下,否则会报错。
    Freee_belowhwm_size: 在HWM(高水位标记线之下的空闲空间数),这个是理论上的可以回收的空间大小。
    Curr_can_shrink: 这个是实际大小与HWM标记之间的差,就是还没有分配出去的空间大小。

    2.对想收缩的表空间中的表及索引进行rebuild

    建立测试表空间

    SQL> create tablespace HWM datafile ‘/oradata/HWM01.dbf’ size 5000M;
    
      Tablespace created;
    
    SQL> alter tablespace HWM add datafile '/oradata/HWM02.dbf' size 5000M;
    
    Tablespace altered
    建立测试案例

    2.1move表空间的long类型

      LONG类型的数据超难管理,不能通过move来传输,也不能通过诸如insert t1 select long_col from t2的方式(或者使用游标可以解决这个问题)请注意在设计中尽量避免使用LONG类型。
    检查当前表空间中的LONG类型字段。

    select /*+use_hash(ds,dtc)*/
    ds.tablespace_name,ds.owner||'.'||ds.segment_name,ds.segment_type,
    dtc.DATA_TYPE,dtc.COLUMN_NAME
    from dba_tab_columns dtc , dba_segments ds
    where dtc.TABLE_NAME = ds.segment_name 
    and dtc.OWNER = ds.owner 
    and ds.tablespace_name not in ('SYSTEM','CWMLITE','EXAMPLE','UNDOTBS2','HWM')
    and data_type = 'LONG'
    View Code

    tablespace

    segmentname

    segtype

    datatype

    colname

    CTL

    CTL.ETL_LOG

    TABLE

    LONG

    EXECUTE_SQL

    CTL

    CTL.PLAN_TABLE

    TABLE

    LONG

    OTHER

    DWD

    DW.PLAN_TABLE

    TABLE

    LONG

    OTHER

    CTL

    OD.PLAN_TABLE

    TABLE

    LONG

    OTHER

    FBI

    FBI.PLAN_TABLE

    TABLE

    LONG

    OTHER

    对long类型的数据处理的一个简单的方法实将LONG类型字段直接修改为LOB类型。

    select /*+use_hash(ds,dtc)*/
    'alter table '||ds.owner||'.'||ds.segment_name||' modify '||dtc.COLUMN_NAME||' clob;'
    from dba_tab_columns dtc , dba_segments ds
    where dtc.TABLE_NAME = ds.segment_name 
    and dtc.OWNER = ds.owner 
    and ds.tablespace_name not in ('SYSTEM','CWMLITE','EXAMPLE','UNDOTBS2','HWM')
    and data_type = 'LONG'
    View Code

    修改类型语句

    alter table CTL.ETL_LOG modify EXECUTE_SQL clob;

    alter table CTL.PLAN_TABLE modify OTHER clob;

    alter table DW.PLAN_TABLE modify OTHER clob;

    alter table OD.PLAN_TABLE modify OTHER clob;

    alter table FBI.PLAN_TABLE modify OTHER clob;

    SQL> alter table CTL.ETL_LOG modify EXECUTE_SQL clob;
    Table altered
    
    SQL> alter table CTL.PLAN_TABLE modify OTHER clob;
    Table altered
    
    SQL> alter table DW.PLAN_TABLE modify OTHER clob;
    Table altered
    
    SQL> alter table OD.PLAN_TABLE modify OTHER clob;
    Table altered
    
    SQL> alter table FBI.PLAN_TABLE modify OTHER clob;
    Table altered
    View Code

    2.2move表空间下的普通table及index

    SQL> alter table tbname move tablespace newtbname;

    Move一个表到另外一个表空间时,索引不会跟着一块move,而且会失效。在创建失效的索引之前,使用到索引的查询语句将会报错。失效的索引需要使用rebuild重创建。

    Alter index index_name rebuild;
    Alter index pk_name rebuild;

    如果我们需要move索引到另外一个表空间,则需要使用rebuild

    Alter index index_name rebuild tablespace tbs_name;
    Alter index pk_name rebuild tablespace tbs_name;

    select  ds.tablespace_name,'alter table '||ds.owner||'.'||ds.segment_name||' move tablespace HWM;'
    from dba_segments ds 
    where ds.tablespace_name not in('SYSTEM','CWMLITE','EXAMPLE','UNDOTBS2',
       'HWM','XDB','WKSYS','CTXSYS','ODM_MTR','USERS','DRSYS','HTEC','HAPPYTREE')
      and ds.segment_type = 'TABLE';
    View Code
    SQL> alter table ODS.SM_PRODUCT_SPEC_SHOW move tablespace HWM;
    Table altered
    
    SQL> alter table DW.D_PRODUCT_INFO move tablespace HWM;
    Table altered
    View Code
    select  ds.tablespace_name,'alter INDEX '||ds.owner||'.'||ds.segment_name||' rebuild tablespace HWM;'
    from dba_segments ds 
    where ds.tablespace_name not in('SYSTEM','CWMLITE','EXAMPLE','UNDOTBS2',
       'HWM','XDB','WKSYS','CTXSYS','ODM_MTR','USERS','DRSYS','HTEC','HAPPYTREE')
      and ds.segment_type = 'INDEX'
    View Code
    SQL> alter INDEX CTL.IDX_TL_ADJUSTMENT_CONFIRMDATE rebuild tablespace HWM;
    Index altered
    
    SQL> alter INDEX CTL.IDX_TL_ADJUSTMENT_ORDER rebuild tablespace HWM;
    Index altered
    View Code

    2.3move表空间下的分区table及index

    和普通表一样,索引也会失效,区别的仅仅是语法而已。
    分区表move基本语法
    如果是单级分区,则使用关键字partition,如果是多级分区,则使用subpartition替代partition。如果分区或分区索引比较大,可以使用并行move或rebuild,parallel(degree 2)。

    重建全局索引
    Alter index global_index rebuild;

    Alter index global_index rebuild tablespace tbs_name;

    重建局部索引
    Alter table tab_name modify partition partition_name rebuild unusable local indexes;

    Alter index local_index_name rebuild partition partition_name tablespace tbs_name;

      2.3.1Move分区表
    select cname
    from (
    select  rownum rm,'alter table '||ds.owner||'.'||ds.segment_name||' move partition '||ds.partition_name||' tablespace HWM;' cname
    from dba_segments ds 
    where ds.tablespace_name not in('SYSTEM','CWMLITE','EXAMPLE','UNDOTBS2',
       'HWM','XDB','WKSYS','CTXSYS','ODM_MTR','USERS','DRSYS','HTEC','HAPPYTREE')
      and ds.segment_type = 'TABLE PARTITION'
    ) c
    where rm between 1 and 100;
    View Code

      循环执行上述语句,直到选不出结果。

    SQL> alter table ODS.CR_PS_INVENTORY_ITEM move partition CR_PS_INVENTORY_ITEM_P070603 tablespace HWM;
    Table altered
    
    SQL> alter table ODS.CR_PS_INVENTORY_ITEM move partition CR_PS_INVENTORY_ITEM_P070604 tablespace HWM;
    Table altered
    View Code

    重建全局索引
        Oracle的全局索引也存储在dba_segments中,并以index标志,而且其重建方式跟普通索引一致,所以在执行忘回导入的时候需要按照move 普通表;move分区表;move全局索引;move分区索引;move lob对象的顺序进行。

    重建分区索引
    视图dba_part_indexes存储分区表的本地索引,查询发现当前系统中不存在本地索引,可以忽略。

    select * from dba_part_indexes t where t.owner not in ('SYSTEM','SH');

    2.3.2move表空间下的LOB类型

      在建立含有Lob字典的表时,oracle会自动为Lob字段建立两个单独的segment,一个用来存放数据(segment_type=LOBSEGMENT),另一个用来存放索引(segment_type=LOBINDEX)。默认他们会存储在和表一起的表空间。

      我们对表move时,LOB类型字段和该字段索引不会跟着move,必须使用单据的语句来执行该字段的move,语法如下:

    Alter table t321 move tablespace HWM;
    Later table t321 move lob(en) store as (tablespace HWM);

    select  'alter table '||dtc.owner||'.'||dtc.TABLE_NAME||' move lob('||dtc.COLUMN_NAME||') store as(tablespace HWM);'
    from dba_tab_columns dtc
    where dtc.OWNER  in('CTL','DW','RPT','OD','ODS','TODS','FBI','DP22','DP23','TCLKING')
      and dtc.DATA_TYPE like '%LOB'
    View Code
    SQL> alter table DP22.D_KPI move lob(KPIFORM) store as(tablespace HWM);
    Table altered
    
    SQL> alter table DP22.D_KPI move lob(KPIFORMDSPN) store as(tablespace HWM);
    Table altered
    View Code

      执行完上述操作步骤后,我们检查tablespace的空间使用情况可以发现,所有相关数据文件的hwm都已经变为0,也就是说所有的空间都已经变为未分配状态。但这时如果我们将数据文件dump出去,会发现原来的数据还在,只不过在数据字典中将其标识为未分配。

    2.4Move对象的逆顺序

    2.4.1普通表对象  

      将普通表对象和分区表对象按照其owner的不同从HWM临时表空间move到其默认的表空间中区。

    select  ds.tablespace_name,'alter table '||ds.owner||'.'||ds.segment_name||' move tablespace '||du.default_tablespace||';'
    from dba_segments ds , dba_users du
    where ds.owner = du.username
      and ds.owner in ('CTL','DW','RPT','OD','ODS','TODS','FBI','DP22','DP23','TCLKING')
      and ds.tablespace_name = 'HWM'
      and ds.segment_type = 'TABLE';
    View Code
    SQL> alter table TODS.CR_PARTY_RELATIONSHIP move tablespace TODSD;
    Table altered
    
    SQL> alter table TODS.CR_PARTY_RELATIONSHIP_TYPE move tablespace TODSD;
    Table altered
    View Code
    2.4.2分区表对象
    select cname
    from (
    select  rownum rm,'alter table '||ds.owner||'.'||ds.segment_name||' move partition '||ds.partition_name||' tablespace '||du.default_tablespace||';' cname
    from dba_segments ds , dba_users du
    where ds.owner = du.username
      and ds.owner in ('CTL','DW','RPT','OD','ODS','TODS','FBI','DP22','DP23','TCLKING')
      and ds.tablespace_name = 'HWM'
      and ds.segment_type = 'TABLE PARTITION'
    ) c
    where rm between 1 and 500;
    View Code

    反复执行上述过程,直到没有记录可以选择。

    SQL> alter table ODS.CR_PS_INVENTORY_ITEM move partition CR_PS_INVENTORY_ITEM_P080513 tablespace ODSD;
    Table altered
    
    SQL> alter table ODS.CR_PS_INVENTORY_ITEM move partition CR_PS_INVENTORY_ITEM_P080514 tablespace ODSD;
    Table altered
    View Code
      2.4.3索引对象   

      索引对象存储的tablespace的命令标准为username+’I’,如果类似的表空间不存在,我们就将索引数据存储到用户的默认表空间中。所以我们可以使用下面的语句将index rebuild到对应的表空间中。

    select  'alter INDEX '||ds.owner||'.'||ds.segment_name||' rebuild tablespace '||nvl(dt.tablespace_name,du.default_tablespace)||';'
    from dba_segments ds , dba_users du, dba_tablespaces dt
    where ds.owner = du.username
      and dt.tablespace_name(+) = du.username||'I'
      and ds.owner in ('CTL','DW','RPT','OD','ODS','TODS','FBI','DP22','DP23','TCLKING')
      and ds.tablespace_name = 'HWM'
      and ds.segment_type = 'INDEX'
    View Code
    2.4.4LOB类型

    Lob类型数据随着table对象存储在对象owner的默认表空间中。

    select  'alter table '||dtc.owner||'.'||dtc.TABLE_NAME||' move lob('||dtc.COLUMN_NAME||') store as(tablespace '||du.default_tablespace||');' 
    from dba_tab_columns dtc,dba_users du
    where dtc.OWNER = du.username
      and dtc.OWNER  in('CTL','DW','RPT','OD','ODS','TODS','FBI','DP22','DP23','TCLKING')
      and dtc.DATA_TYPE like '%LOB'
    View Code
    SQL> alter table FBI.TIME_FORMAT move lob(FORMAT) store as(tablespace FBI);
    Table altered
    
    SQL> alter table FBI.URLTABLE move lob(DETAIL) store as(tablespace FBI);
    Table altered
    
    SQL> alter table OD.PLAN_TABLE move lob(OTHER) store as(tablespace OD);
    Table altered
    View Code

    3.收缩空闲表空间

    首先,如果没有分配的空间不足100M,则不考虑收缩。
    收缩目标:当前数据文件大小 - (没分配空间- 100M)×0.8

    select /*+ ordered use_hash(a,c) */
      'alter database datafile '''||a.file_name||''' resize '
       ||round(a.filesize - (a.filesize - c.hwmsize-100) *0.8)||'M;',
      a.filesize,
      c.hwmsize
    from 
    (
    select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
    ) a,
    (
    select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
    group by file_id) c
    where a.file_id = c.file_id
      and a.filesize - c.hwmsize > 100
    收缩表空间
    select 
    owner
    ,segment_name
    ,segment_type
    ,tablespace_name
    from dba_extents
    where file_id=6
    and 193673
    between block_id and block_id + blocks - 1
    ;
    查义最大数据块对应的表
  • 相关阅读:
    php 基本连接mysql数据库和查询数据
    HTTP/2 简介
    MySQL数据库 utf-8与utf8mb4
    AJAX请求中出现OPTIONS请求
    精力充沛的管理者,要不要“闲”下来?
    【转】微信开发出现“该公众号暂时无法提供服务,请稍后再试”的坑
    Nginx笔记(一):安装
    Tomcat分析
    Redis集群搭建与使用
    微信JS-SDK实现上传图片功能
  • 原文地址:https://www.cnblogs.com/HondaHsu/p/3757058.html
Copyright © 2020-2023  润新知