ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 删除大表T_HP_PRODUCT

删除大表T_HP_PRODUCT

原创 Linux操作系统 作者:wadekobe9 时间:2012-04-06 16:57:32 0 删除 编辑

删除一张大表的过程

1,直接删除,删除4万行用了半小时

2,建好表结构(包括索引和约束),然后insert ,,, As Select * From ,这种方式将undo插入满了,虽然我这里用的是appendnologging的方式。

3,直接create Table As Select * From ,,,这种方式建好表只要6分钟,然后就是建立索引和约束了。

 

 

-----------------------------------------------------------------

删除的第一部始终是检查它是否当了别人的’部门‘,虽然直接删除此表数据

会报外键约束的错误,但是通过rename的方式移表可以跳过外键检查,这里

就会很危险,所以必须要检查清楚

select   a.owner 主键拥有者,

         a.table_name 主键表,

         b.column_name 主键列,

         C.OWNER 外键拥有者,

         c.table_name 外键表,

         d.column_name 外键列

from user_constraints a,

     user_cons_columns b,

     user_constraints C,

     user_cons_columns d

where  a.constraint_name=b.constraint_name

and C.R_CONSTRAINT_NAME=a.constraint_name

and c.constraint_name=d.constraint_name

and a.constraint_type='P'

and a.table_name='T_HP_PRODUCT' --需要查看主外键关系的表

order by a.table_name

 

它没有当别人的部门,可以直接删除它的数据,这里也不会

报外键约束错误。

-----------------------------------------------------------------

 

Select Count(*) From T_HP_PRODUCT

Select Max(SALE_DATE) From T_HP_PRODUCT  --2050/12/31

Select Min(SALE_DATE) From T_HP_PRODUCT  --2010/1/1

-----------------------------------------------------------------

-----------------------------------------------------------------

 

<1>采用直接删除的方法,4万行的数据居然用了半个小时,这里绝对是

外键,索引和碎片的问题

Delete From T_HP_PRODUCT Where SALE_DATE  

Between to_date('2010-01-01 00:00:00','yyyy/MM/DD/ HH24:MI:SS')

    and to_date('2010-03-02 00:00:00','yyyy/MM/DD/ HH24:MI:SS')

 

查看此表发现者张表上面有很多索引

Select User_Ind_Columns.Index_Name,

       Index_Type,

       Uniqueness,

       Last_Analyzed,

       Column_Name,

       User_Indexes.Table_Name,

       Tablespace_Name

  From User_Indexes, User_Ind_Columns

 Where User_Indexes.Index_Name = User_Ind_Columns.Index_Name

   And User_Indexes.Table_Name = 'T_HP_PRODUCT';

 

直接删除的方法多半行不通

--------------------------------------------------------------------

 

 

-----------------------------------------------------------------

-----------------------------------------------------------------

<2>我先将表T_HP_PRODUCT的建表结构提出来,建立好表以及表上的索引和

约束,然后直接将需要的数据插入此表,并准备用rename的方式移动此表

下面的是要插入的数据行数,此处建立的是表T_HP_PRODUCT_1

 

Select Count(*)  From T_HP_PRODUCT Where

SALE_DATE>=  to_date('2011-01-01 00:00:00','yyyy/MM/DD/ HH24:MI:SS')

 

首先让T_HP_PRODUCT_1不记日志

Alter Table T_HP_PRODUCT_1 nologging

 

然后通过直接路径插入,我在晚上凌晨运行此条SQL

Insert /*+append*/ Into t_Hp_Product_1 

Select * From t_Hp_Product

Where Sale_Date >=To_Date('2011-01-01 00:00:00', 'yyyy/MM/DD/ HH24:MI:SS')

        

        

第二天上班报出此错:

ora-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS2' 

可以看见,是undo表空间UNDOTBS2被插满了,但是这种情况数据库并没有挂起,

插入的操作被自动中断了然后回滚了。表空间满了是不是不会引起数据库挂起

只要当磁盘上面的空间满了之后数据库才会挂起。

这里插入失败应该是上面的索引还会写undo,因为直接插入应该是不写索引的

我现在将表的索引全部删除,然后使外键失效

---------------------------------------------------------------

 

 

 

-----------------------------------------------------------------

-----------------------------------------------------------------

<3>create Table As Select * From 的方式来建表,这种情况下出来的表

是没有索引和约束的,下的这种情况运行起来要大大快于上面的情况,那么

是不是可以把上面慢的情况完全定位到索引和外键约束身上去了呢?

 

--下面命令用时6分钟半钟,这个涨I/O(应该有50142652)

Create Table t_Hp_Product_2 As Select * From t_Hp_Product

Where Sale_Date >= To_Date('2011-01-01 00:00:00', 'yyyy/MM/DD/ HH24:MI:SS')

 

要用operation_time 把差异数据补回去了

 

--这个不涨I/O5分钟完成,这张表移动过去后吃了5G左右空间,现在还没添加索引

 alter table t_Hp_Product_2 move tablespace USERLOB;

 

Select Count(*) From t_Hp_Product_2 --50142652

Select Count(*) From t_Hp_Product  Where Sale_Date >= To_Date('2011-01-01 00:00:00', 'yyyy/MM/DD/ HH24:MI:SS') --50142730

--49591190

Select Max(operation_time) From t_Hp_Product 

---------------------------------------

在创建完约束和索引后,添加索引的过程仍然消耗i/o,一个索引5分钟左右。

 

要用operation_time 把差异数据补回去了

 

Select Max(operation_time) From t_Hp_Product 

Insert Into t_Hp_Product_2 Select * From  t_Hp_Product Where operation_time> To_Date('2012-3-26 17:29:06', 'yyyy/MM/DD/ HH24:MI:SS')

 

Rename t_Hp_Product To t_Hp_Product_bakk;

Rename t_Hp_Product_2 To t_Hp_Product;

 

 

 

exec dbms_stats.gather_index_stats('gc','PK_T_HP_PRODUCT');

 

select PRODUCT_ID From  t_Hp_Product_2

Minus

select PRODUCT_ID From  t_Hp_Product

 

Delete From t_Hp_Product_2 Where product_id In (

'462473047',

'462473048',

........

'513828813'

 

)


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10678398/viewspace-720574/,如需转载,请注明出处,否则将追究法律责任。

下一篇: nologgin和append
请登录后发表评论 登录
全部评论

注册时间:2010-11-30

  • 博文量
    36
  • 访问量
    56664