我们有一张大表,有大约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周的完成时间。总之,我需要找到;
从大表中删除多行的方法。有什么建议吗?
答案 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天。并且有额外的时间用于网络,写入控制台等。以块为单位修改数据并不总是可以避免,但至少应该尝试使用更大的块。
正如其他人所提到的,分区可能非常有用。但是分区存在很多缺点,如果这是一个罕见的过程,那么以简单的方式完成它可能是值得的。