`
tjmzgn
  • 浏览: 159708 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

oracle定时添加或删除分区表的分区

阅读更多
这几天,根据业务的需求和性能的考虑,需要定时删除历史数据,表里
只保留最近指定的wareid的数据,考虑删除时对表的影响及便利性,我决定
把这个表建立成分区表,定期添加和删除分区

步骤:


1. 创建相关procedure
    pro_ADD_PARTITION_wareid    ---用户添加分区的过程
    pro_DROP_PARTITION_wareid   ---用户删除分区的过程
    pro_expdatainto_his         ---用户备份要删除分区数据的过程


2.创建系统上的脚本


3.用cron做定时任务


1. 创建相关procedure


CREATE OR REPLACE PROCEDURE pro_ADD_PARTITION_wareid(tablename      varchar2, ---要添加分区的表
                                                     partNum        NUMBER, --添加分区的个数
                                                     TableSpaceName VARCHAR2, --表空间名
                                                     wareidnum      number default 100 ---分区的范围
                                                     ) AS
  /*******************************************************
  author:skate
  time  :2009/02/28
  功能:添加分区表的指定分区
  说明:可以通过定时任务来完成自动添加分区,添加后要检查索引的状态
        最好是重建索引,以达到对表的分析
  eg:  exec pro_add_partition_wareid('d_order_bak',2,'yytickets','200');
  ********************************************************/

  v_SqlExec     VARCHAR2(2000); --DDL语句变量
  v_Partwareid1 number; --创建分区的wareid
  v_err_num     NUMBER; --ORA错误号
  v_err_msg     VARCHAR2(100); --错误描述

  v_part_wareid_max number; --tablename 表分区的最大wareid号
  v_begin           number; ----字符串的开始位置
  v_count           number; ----取多少个字符串
  v_part_name       varchar2(100); --要添加分区表的名称的前缀

BEGIN

  ----字符串的开始位置
  select INSTR(partition_name, '_', -1, 1) + 1
    into v_begin
    from user_tab_partitions
   where table_name = UPPER(tablename)
     and rownum < 2;

  ----取多少个字符串
  select length(partition_name) - v_begin + 1
    into v_count
    from user_tab_partitions
   where table_name = UPPER(tablename)
     and rownum < 2;

  --查询分区表tablename的最大wareid值
  select max(to_number(SUBSTR(partition_name, v_begin, v_count)))
    into v_part_wareid_max
    from user_tab_partitions
   WHERE table_name = UPPER(tablename);

  ---计算分区表的名称
  select SUBSTR(partition_name, 1, v_begin - 1)
    into v_part_name
    from user_tab_partitions
   WHERE table_name = UPPER(tablename)
     and rownum < 2;

  v_Partwareid1 := v_part_wareid_max;

  FOR i IN 1 .. partNum LOOP

    v_Partwareid1 := v_Partwareid1 + wareidnum; ----计算要添加分区的wareid

   
   
    v_SqlExec := 'ALTER TABLE ' || tablename || ' ADD PARTITION ' ||
                 v_part_name || v_Partwareid1 || ' values less than(' ||
                 v_Partwareid1 || ') TABLESPACE ' || TableSpaceName;
    dbms_output.put_line('创建 d_order 表分区' || i || '=' || v_SqlExec);
    DBMS_Utility.Exec_DDL_Statement(v_SqlExec);

  END LOOP;
  /*EXCEPTION
  WHEN OTHERS THEN
    v_err_num := SQLCODE;
    v_err_msg := SUBSTR(SQLERRM, 1, 100);
    dbms_output.put_line('pro_ADD_PARTITION_wareid执行出现异常,错误码=' ||
                         v_err_num || '错误描述=' || v_err_msg);*/
commit;                       
END pro_ADD_PARTITION_wareid;

##########################################################################################

删除分区的procedure:

CREATE OR REPLACE PROCEDURE pro_DROP_PARTITION_wareid(tablename    varchar2, ---要删除分区表的名称
                                                      beforewareid NUMBER default 200 --要保留最新多少wareid
                                                      ) As

  /*******************************************************
  author:skate
  time  :2009/02/28
  功能:删除分区表的指定分区
  说明:可以通过定时任务来完成自动删除分区,删除后要检查索引的状态
        最好是重建索引,以达到对表的分析

  eg:exec pro_drop_partition_wareid('d_order_bak',10800);
  ********************************************************/

  v_SqlExec VARCHAR2(2000); --DDL语句变量
  v_err_num NUMBER; --ORA错误号
  v_err_msg VARCHAR2(100); --错误描述

  v_begin       number; ----字符串的开始位置
  v_count       number; ----取多少个字符串
  v_ware_id     number;
  v_max_ware_id number;
  b  varchar2(10);
 
  cursor cursor_table_part is
    select partition_name
      from user_tab_partitions
     WHERE table_name = UPPER(tablename)
       AND SUBSTR(partition_name, v_begin, v_count) < v_ware_id
     ORDER BY partition_name;
---为禁用或启用约束而定义的游标
    cursor cursor_const_part is
    select b.constraint_name
      from user_constraints a, user_cons_columns b
      where a.table_name=b.table_name
        and   a.constraint_name=b.constraint_name
        and   a.owner='TICKETS'
        and   a.table_name=upper(tablename);
       
    ---为索引失效而重建索引定义游标
    cursor cursor_idx is
    select index_name
      from user_indexes
     where table_name = UPPER(tablename)
       and status = 'UNUSABLE';
  

  record_table_oldpart cursor_table_part%rowType;
  record_cursor_const_part cursor_const_part%rowtype;
  record_cursor_idx cursor_idx%rowtype;

BEGIN

  ----字符串的开始位置
  select INSTR(partition_name, '_', -1, 1) + 1
    into v_begin
    from user_tab_partitions
   where table_name = UPPER(tablename)
     and rownum < 2;

  ----取多少个字符串
  select length(partition_name) - v_begin + 1
    into v_count
    from user_tab_partitions
   where table_name = UPPER(tablename)
     and rownum < 2;

  --确定要删除的最大wareid
  select max(to_number(substr(partition_name, v_begin, v_count)))
    into v_max_ware_id
    from user_tab_partitions
    where table_name = UPPER(tablename);

  --select max(w.ware_id) into v_max_ware_id from d_ware w;
  v_ware_id := v_max_ware_id - beforewareid;

    ---暂时禁用约束
    open cursor_const_part;
    loop
      fetch cursor_const_part into record_cursor_const_part;
      exit when cursor_const_part%notfound;
   
      execute immediate 'alter table '||tablename||' disable constraint '||record_cursor_const_part.constraint_name||' cascade';
   
    end loop; 
    close cursor_const_part;

  open cursor_table_part;
  loop
    fetch cursor_table_part
      into record_table_oldpart;
    exit when cursor_table_part%notfound;

    if substr(record_table_oldpart.partition_name, v_begin, v_count) <
       v_ware_id then
      --把要删除的数据提前备份到历史表里
      pro_expdatainto_his(tablename,record_table_oldpart.partition_name,b);
     
      --验证是否可以删除指定的分区表
      if (b='Y' or b='R') then
     
       
         --删除 tablename 表分区
         
          v_SqlExec := 'ALTER TABLE ' || tablename || ' DROP PARTITION ' ||
                       record_table_oldpart.partition_name;
          dbms_output.put_line('删除' || tablename || '表分区=' || v_SqlExec);
          DBMS_Utility.Exec_DDL_Statement(v_SqlExec);
         
       
         
      elsif b='N' then
      exit;
      end if;
        
    end if;
  end loop;
  close cursor_table_part;
 
      ---启用约束
       open cursor_const_part;
         loop
          fetch cursor_const_part into record_cursor_const_part;
          exit when cursor_const_part%notfound;
         
           execute immediate 'alter table '||tablename||' enable novalidate constraint '||record_cursor_const_part.constraint_name;
         
         end loop; 
         close cursor_const_part;
        
     --重建失效的索引
        open cursor_idx;
        loop
          fetch cursor_idx into record_cursor_idx;
          exit when cursor_idx%notfound;
         
          execute immediate 'alter index ' ||record_cursor_idx.index_name||' rebuild';
        
         end loop;
         close  cursor_idx;

  /*EXCEPTION
  WHEN OTHERS THEN
    v_err_num := SQLCODE;
    v_err_msg := SUBSTR(SQLERRM, 1, 100);
    dbms_output.put_line(pro_DROP_PARTITION_wareid ||
                         '执行出现异常,错误码=' || v_err_num ||
                         '错误描述=' || v_err_msg);*/


END pro_DROP_PARTITION_wareid;


#########################################################################################

这个存储过程用户在删除分区的时候,用户备份所删除的分区表


create or replace procedure pro_expdatainto_his(tablename      varchar2,---要导数据的表名
                                                part_tablename varchar2,---要导数据的分区表名
                                                issuccess      in out varchar2)--返回是否导入成功 (Y:成功 N:失败 R:之前已经导入过了)
                                                 as

  v_SqlExechis VARCHAR2(2000); --DDL语句变量
  v_SqlExec    VARCHAR2(2000); --DDL语句变量
  v_count      number(30);     --本次导入的数据行数
  v_expcount   number(30);     --历史表中有多少符合本次导入的行数
  /*******************************************************
  author:skate
  time  :2009/04/15
  功能:把预删除的分区表的数据提前导入到历史表中
  说明:这个程序是配合定时删除分区的过程,pro_add_partition_wareid调用
        此过程,本过程适合如下表:
          D_ORDER
          D_ORDER_DETAIL
          D_PRINT_BATCH
          d_batch_detail
        
         如果想让其适合其他表,只要做简单修改即可
         
  eg:  exec pro_expdatainto_his('d_order','D_ORDER_P_31100',b);
 
  注意:本procedure的表名用到了变量,所以要用动态sql来执行:execute immediate
  ********************************************************/ 
 
begin


  if upper(tablename) = 'D_ORDER' then
 
    v_SqlExec := 'select count(1) from ' || tablename || ' partition(' ||
                 part_tablename || ')';
    --准备导入多少行数据            
    execute immediate v_SqlExec
      into v_count;
   --执行导入操作
    execute immediate 'insert into ' || tablename ||
                      '_his  select * from '||tablename||' partition(' ||
                      part_tablename || ') nologing';
 
    v_SqlExechis := 'select count(1)  from ' || tablename || '_his th ,' ||
                    tablename || ' partition(' || part_tablename ||
                    ') t where t.order_id=th.order_id';
 
   --在历史表中有多少和本此导入相同的记录
    execute immediate v_SqlExechis
      into v_expcount;
 
  elsif upper(tablename) = 'D_ORDER_DETAIL' then
 
    v_SqlExec := 'select count(1) from ' || tablename || ' partition(' ||
                 part_tablename || ')';
    execute immediate v_SqlExec
      into v_count;
 
    execute immediate 'insert into ' || tablename ||'_his  select * from '||tablename||' partition('||part_tablename || ') nologing';
 
    v_SqlExechis := 'select count(1)  from ' || tablename || '_his th ,' ||tablename || ' partition(' || part_tablename ||') t where t.detail_id=th.detail_id';
 
    execute immediate v_SqlExechis
      into v_expcount;
 
  elsif upper(tablename) = 'D_PRINT_BATCH' then
 
    v_SqlExec := 'select count(1) from ' || tablename || ' partition(' ||
                 part_tablename || ')';
    execute immediate v_SqlExec
      into v_count;
 
    execute immediate 'insert into ' || tablename ||
                      '_his  select * from '||tablename||' partition(' ||
                      part_tablename || ') nologing';
 
    v_SqlExechis := 'select count(1)  from ' || tablename || '_his th ,' ||
                    tablename || ' partition(' || part_tablename ||
                    ') t where t.batch_id=th.batch_id';
 
    execute immediate v_SqlExechis
      into v_expcount;
 
  elsif upper(tablename) = upper('d_batch_detail') then
 
    v_SqlExec := 'select count(1) from ' || tablename || ' partition(' ||
                 part_tablename || ')';
    execute immediate v_SqlExec
      into v_count;
 
    execute immediate 'insert into ' || tablename ||
                      '_his  select * from '||tablename||' partition(' ||
                      part_tablename || ') nologing';
 
    v_SqlExechis := 'select count(1)  from ' || tablename || '_his th ,' ||
                    tablename || ' partition(' || part_tablename ||
                    ') t where t.batch_detail_id=th.batch_detail_id';
 
    execute immediate v_SqlExechis
      into v_expcount;
 
  end if;

--验证是否导入成功,如果成功就commit,否则rollback
  if v_count = v_expcount then
    issuccess := 'Y';
    commit;
  elsif v_count * 2 = v_expcount then
    issuccess := 'R';
    rollback;
  else
    issuccess := 'N';
    rollback;
  end if;

end pro_expdatainto_his;

################################################################

2.创建系统上的脚本

[oracle@svr-db-test sh]$ more ticket_del_part.sh
cd /home/oracle/sh
date
sqlplus /nolog @ ticket_del_part.sql
date
[oracle@svr-db-test sh]$


[oracle@svr-db-test sh]$ more ticket_del_part.sql
connect tickets/123456
set timing on
exec  pro_drop_partition_wareid('d_order',50);
exec  pro_drop_partition_wareid('d_order_detail',50);
exec  pro_drop_partition_wareid('D_PRINT_BATCH',50);

exit
[oracle@svr-db-test sh]$

3.用cron做定时任务

在oracle用户的crontab下增加一条定时任务即可:


#delete partition

1 */3 * * * sh /home/oracle/sh/ticket_del_part.sh >> /home/oracle/sh/ticket_del_part.log


简单吧!!!


真TMD累啊!! 回家


------end-----
分享到:
评论

相关推荐

    oracle定时删除表空间的数据并释放表空间

    7. **表分区和段压缩**:为了更有效地管理表空间,可以考虑对大表进行分区,根据日期或其他业务关键字段将数据分段存储。此外,Oracle还提供了压缩选项,如ROW STORE COMPRESSION和COLUMN STORE COMPRESSION,可以在...

    Oracle 分区表自动维护脚本

    标题中提到的“Oracle 分区表自动维护脚本”是指一种在Oracle数据库系统中用于管理和维护分区表的自动化脚本。这种脚本可以执行多个维护任务,包括但不限于:增加新分区、删除历史分区、拆分分区和数据清除等操作。...

    unix AIX 环境下 exp 备份 Oracle 分区表实例

    在Unix AIX环境下进行Oracle分区表的备份操作是IT领域中一项重要的技能,尤其是在处理大量数据和维护系统稳定性时。本文将深入解析如何在Unix AIX环境下使用exp工具备份Oracle分区表,包括环境配置、备份策略及恢复...

    ORACLE数据定时导入导出工具

    Oracle 数据定时导入导出工具是数据库管理中一个关键的组件,尤其对于企业级数据库系统而言,数据的安全性和可恢复性至关重要。Oracle 提供了多种工具和技术来实现这一目标,包括 Data Pump、SQL*Loader 和 RMAN...

    让ORACLE跑得更快

    分区技术通过将表、索引或索引组织表中的数据分布到不同的物理部分,从而提高了数据管理的灵活性和查询性能。分区可以基于多个列,但通常情况下,时间序列数据如销售数据非常适合使用范围分区。 在使用范围分区时,...

    Oracle-API.zip

    Oracle 10g 还引入了高级特性,如分区表、物化视图、材料化查询表等,这些都可通过 API 进行操作。分区表可以提高大数据量查询的效率,物化视图则可以预计算复杂查询的结果,提高查询速度。 总的来说,Oracle API ...

    oracle 数据按主键删除慢问题的解决方法

    在Oracle数据库中,数据的删除操作可能由于多种原因而导致执行缓慢,尤其是在涉及到具有大量数据的表时。针对标题中提到的“按主键删除慢”的问题,以下是一些可能的原因以及相应的解决方法。 首先,Oracle中删除...

    xxl-job-2.4.0定时任务框架Oracle版本

    - 例如,可能修改了表的创建语句,以适应Oracle的分区、索引、存储过程等特性,或者修正了可能导致兼容性问题的特定SQL操作。 - 这种整改有助于避免在Oracle中运行时可能出现的数据类型不匹配、语法错误等问题,...

    搜索引擎全文检索技术 oracle

    Oracle Text的核心在于创建和维护文本索引,这些索引能够快速定位含有特定词汇或短语的记录。 2. **创建全文索引** 创建全文索引是全文检索的第一步。在Oracle中,这通常通过使用`CREATE INDEX`语句完成,结合`...

    使用dbms_stats包手工收集统计信息

    schema_stats 过程时,如果你想要知道自从上一次分析统计数据以来,发生了多少次插入、更新和删除操作,可以使用 alter table xxx monitoring 命令,Oracle 会用 dba_tab_modifications 视图来跟踪发生变动的表。...

    Oracle优化原则整理

    根据需求,可以设置物化视图的刷新策略,如实时、定时或手动刷新。 8. **分区技术**:通过分区,可以将大表划分为较小、更易管理的部分,提升查询性能和维护效率。例如,范围分区、列表分区、哈希分区等。 9. **表...

    Oracle数据库巡检报告

    - **2.1.11 检查当前crontab任务**:通过`crontab -l`命令查看定时任务列表,确认是否有未授权或异常的任务。 ##### 2.2 数据库空间监控 - **2.2.1 检查数据库的大小,和空间使用情况** - 使用`dbms_space.report...

    oracle及reports培训教程.asp.rar

    7. **分区**:对于大数据量的表,Oracle提供分区技术,将大表逻辑上分为更小、更易管理的部分,提高查询性能。 8. **备份与恢复**:Oracle提供了多种备份策略,包括物理备份和逻辑备份,以确保数据安全。RMAN(恢复...

    《Oracle查询优化改写技巧与案例》PDF版本下载.txt

    - **避免全表扫描**:通过添加合适的过滤条件或使用覆盖索引,减少全表扫描的频率。 #### 3.2 提示使用 - **显式提示**:使用/*+ INDEX */等显式提示引导优化器选择特定的执行计划。 - **动态采样**:调整动态采样...

    ORACLE数据库资料整理【经典】

    **表分区设计**则用于优化大型表的性能,通过将大表划分为更小、更易管理的部分来提高查询效率。 4. **视图设计**:视图是从一个或多个表中创建的虚拟表,可以简化复杂查询,隐藏敏感数据,或者提供特定用户的定制...

    oracle数据库文本文档

    除了基本的数据管理功能外,Oracle数据库还具备一系列高级特性,如分区、索引组织表、数据压缩、实时应用集群等,这些特性进一步增强了Oracle数据库的性能和灵活性。 1. **分区**:允许将大表分割成较小的部分,以...

    ORACLE命令整理

    5. **分区表**:大表的优化策略,将大表分割成逻辑上独立的分区,便于管理和提高查询性能。 6. **物化视图**:预计算的查询结果,用于加速查询,可通过定时刷新保持最新。 7. **临时表**:用于临时存储数据,每个...

    oracle数据库备份脚本

    `expdp` 支持多种数据导出方式,包括表、表空间、用户等,并且支持压缩、分区等功能。 ##### 3.2 常用参数 - **directory**:指定存放备份文件的位置。 - **schemas**:指定要备份的模式。 - **tables**:指定要...

    Oracle详细资料

    2. 物理结构优化:包括选择合适的表空间、数据文件、段、区和块的大小,以及合理的表分区策略,如范围分区、列表分区、散列分区等。 3. 索引管理:创建适当的索引可以加速查询,但过多的索引会增加写操作开销。应...

    优化Oracle库表设计的若干方法

    考虑更新频率和空间占用,适时选择刷新策略:立即刷新、定时刷新或按需刷新。 9. **表的物理组织** 表的物理组织形式,如堆表、索引组织表(IOT)、B树索引等,影响查询效率。根据数据访问模式和业务需求选择合适...

Global site tag (gtag.js) - Google Analytics