从大文本文件导入数据库时​​获取SystemOutOfMemoryException的方法

我们正在使用ZyWall来保护我们的服务器免受外部入侵。 它生成每日日志文件,大小超过GB,有时为2 GB。 它们通常包含超过1000万行。 现在我的任务是编写一个将这些行导入Oracle数据库的应用程序。 我是用C#编写的。 我目前正在做的是:

  1. 我逐行阅读日志文件。 我不立刻加载整个文件:

    使用(StreamReader reader = new StreamReader(“C:\ ZyWall.log”)){while((line = reader.ReadLine())!= null)……}

  2. 每行阅读我根据其中的逗号将行分成几部分。

    string [] lines = line.Split(new Char [] {‘,’},10);

  3. 然后我遍历lines数组,为预定义的DataTable对象创建一个新Row,并将数组值分配给该行中的列。 然后我将行添加到数据表中。

在读取所有行到数据表之后,我使用OracleBulkCopy将数据写入数据库中具有相同结构的物理表。 但问题是,当我将行添加到Datatable对象时,我得到SystemOutOfMemoryException,这是第3步。 如果我注释掉第3步然后在任务管理器中我看到应用程序消耗了大约17000 K的稳定内存量但是如果我取消注释该步骤,则内存使用量会增长,除非没有足够的内存来分配。 还有一种方法可以使用BulkCopy来执行此操作,还是我必须手动执行此操作? 我使用BulkCopy因为它比逐行插入行更快。

如果我理解正确,那么您将在表格中加载每一行,该表格变得如此之大,以至于达到系统内存的限制。
如果是这样,你应该找到这个限制。 (例如1000000行)。 在此之前停止读取行,并使用OracleBulkCopy写入目前为止加载的行。 清理你的记忆然后重新开始。 所以让我用伪代码总结一切。

int lineLimit = GetConfiguration("lineLimit"); int lineNumber = 0; DataTable logZyWall = CreateLogTable(); using(StreamReader reader=new StreamReader("C:\ZyWall.log")) { while ((line=reader.ReadLine())!=null) { DataRow row = ParseThisLine(line); logZyWall.Rows.Add(row); lineNumber++; if(lineNumber == lineLimit) { WriteWithOracleBulkCopy(logZyWall); logZyWall = CreateLogTable(); lineNumber = 0; } } if(lineNumber != 0) WriteWithOracleBulkCopy(logZyWall); } 
Interesting Posts