码迷,mamicode.com
首页 > 数据库 > 详细

ORACLE 关于DELETE操作的一些事

时间:2015-03-30 13:00:05      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:

  在实际工作中,经常会遇到这样的需求:定期对已经过期的数据进行删除,释放服务器资源。例如,我们定义了一个定时器任务,在凌晨2点开始执行,这个任务就是删除1个月之前的数据,以释放空间。

  最初的时候,我们可以这么写:

  delete from table_name where t_time < to_date(‘2015-04-01’,’yyyy-mm-dd’)

  这个一个最简单不过的根据条件进行删除数据的操作。乍看之下没有任何问题,但是当数据量十分庞大的时候,一个月就有上千万条数据的时候,就会大量占用数据库的资源。凌晨2点执行的语句,可能要到中午12点才能执行完毕,以至于这段时间内,查询操作就会变得无比缓慢,平时半分钟返回结果的查询,此时就会变成了十几分钟。这显然是不可取的。

  

  在delete操作中,sql语句首先要扫描表或者索引找到符合条件的记录,然后把它们删除。这个过程会消耗大量的CPU资源和产生大量的IO,同时还会产生大量的undo数据。一次性删除10000条左右的数据,差不多要产生了10000多个数据块读取,将近3MB的redo日志。

  与delete相比,drop和truncate操作消耗的资源要相对小的多。同样是删除10000条数据,delete会产生10000多次的数据块读取;dro会产生1100多次的数据块读取;truncate则只有600多次的数据块读取。

 

  一般情况下,我们删除表中数据是为了释放空间。delete操作不能释放空间,删除了哪个表中的数据,腾出的空间也只能提供给哪个表使用,并不能让给其他的对象使用。如果希望通过删除数据腾出空间给其他对象使用,delete是不行的。

  drop和truncate操作腾出的空间则能够提供其他对象使用。

 

   也许有人会问,drop和truncate操作消耗的系统资源和速度是比delete快,但是truncate会清空表中所有的数据,drop更是连表都一起删除了,这样显然不能实现博客开始提出的定时删除表中上个月数据的功能。这种情况下我们就要用到表分区了。

  根据时间字段t_time按照每个月一个分区的方式来创建一个范围分区:

partition by range(t_time)

(

partition table_name_2015_1 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_2 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_3 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_4 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_5 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_6 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_7 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_8 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_9 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_10 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_11 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘)),

partition table_name_2015_12 values less than(to_date(‘01/01/2015‘,‘dd/mm/yyyy‘))

);

  这样按照月份删除数据的时候,我们可以:

  alter table table_name truncate partition table_name_2015_1;

  或者:

  alter table table_name drop partition table_name_2015_1;

  还有人会问,truncate删除的数据是不会留下undo日志的,不能进行数据回滚等操作。其实在实际开发中,历史数据一般都会移植到另外的数据库中进行保存,这种数据库称作为离线数据库或者历史数据库。

  只要我们在删除表空间中数据前,先通过程序或者数据库等操作方式将数据先备份到历史数据库中,在删除表空间中的数据。

 

  一般情况下,只有大数据的情况下才会用到表分区,只有几万条数据或者千单位的数据的时候,使用传统的delete操作就可以了,性能上并不会有什么太大的区别。

ORACLE 关于DELETE操作的一些事

标签:

原文地址:http://www.cnblogs.com/gaexirnn/p/4377654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!