如何从Oracle大表中删除多行?

时间:2013-03-06 11:38:47

标签: oracle11g delete-row multiple-records

我们有一张大表,有大约3.8亿条记录。我们需要删除比2013年1月1日更早的2.5亿条记录。我用谷歌搜索了一些方法,但我并不满意。常见和最快的方式如下:

create table newbig_table unrecoverable as
select * from oldhuge_table
where <condition is reverse of delete condition>

最后将新表重命名为原始名称,但连续插入的新记录是什么?

主要问题是;此表是在线表,并由许多代理使用。所以我需要删除不减慢系统速度,也不要影响新记录。我自己尝试了这种方法:

using (SqlConnection connData = new SqlConnection("Data Source=xxx;User ID=xxx;password=xxx;Initial Catalog=xxx"))
            {
                connData.Open();
                int cnt = 0;
                long total = 0;
                long startID = 1039142601;
                long endID = 1385795368;
                long recCount = endID  - startID;
                cnt++;
                long delRange = 400; //deletes 400 by 400

                for (long i = 1; i < endID; i++)
                {                        
                    startTime = DateTime.Now;

                    string deleteSql = "delete from DivaSessionFlowLog  " +
                                    " where ID >= " + startID.ToString() +
                                    " and ID <= " + (startID + delRange).ToString();

                    int strID = (int)((new SqlCommand(deleteSql, connData)).ExecuteNonQuery());
                    total = total + strID;
                    Console.WriteLine(i.ToString() + ":" + strID.ToString() + " OK DelCnt:" + total.ToString() + " ID:" + startID.ToString() + " Rest:" + String.Format("{0:#,#}", (recCount - total)) + " Time:" + DateTime.Now.ToString("HH':'mm':'ss"));

                    Thread.Sleep(200);
                    startID = startID + delRange;
                    i = startID;
                }

为了不减慢系统程序的睡眠时间为200毫秒。但是,我计算了 2周的完成时间。总之,我需要找到;

  • 不会减慢数据库的速度
  • 不会持续影响新插入的记录

从大表中删除多行的方法。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

最好的方法是将表分区,以便可以删除旧的分区。

但是,如果您需要修改表,并且不要忘记该表可能具有特权,索引,触发器等,并且您需要在整个过程中保持它可用,那么您需要使用DBMS_Redefinition

此外,UNRECOVERABLE是旧语法,但您不希望使用现代等效语法,因为如果您在系统上出现介质故障,则会丢失表和数据。

答案 1 :(得分:0)

按日期对表格进行分区对这里有很大帮助。与逐个删除行相比,可以更快地删除特定分区的内容。

看看http://www.oracle-base.com/articles/misc/partitioning-an-existing-table.php;这描述了如何从非分区表移动到分区表。

答案 2 :(得分:0)

delRange从400更改为40000或400000。

根据我的计算,您的流程将在Thread.Sleep(200)中花费5.015天。并且有额外的时间用于网络,写入控制台等。以块为单位修改数据并不总是可以避免,但至少应该尝试使用更大的块。

正如其他人所提到的,分区可能非常有用。但是分区存在很多缺点,如果这是一个罕见的过程,那么以简单的方式完成它可能是值得的。