【发布时间】:2012-03-31 04:37:17
【问题描述】:
我有一个巨大的日志文件,其中大约有 1500 万行。我必须将所有这些行移植到 Oracle 数据库。这是我要做的:
- 我读取数据表的行(行用逗号分隔,这样 它们形成列)。我通过 StreamReader 阅读了这些行并将其放入 使用,以便它在完成阅读后摆脱它。
- 我放置了一个计数器,该计数器每读取到 DataTable 的行就加 1。
- 当该计数器达到 40.000 时,我在 OracleBulkCopy 的帮助下将所有行导入数据库。
-
导入完成后我会说:
bulkCopier.Dispose();
dataTable.Dispose();
但是,这无济于事。在任务管理器中,我看到内存使用量不断增长,直到内存不足。现在我的问题是Dispose() 方法不会立即释放内存吗?如果是这样,那么为什么内存使用量会累积,好像所有 DataTable 和 OracleBulkCopy 对象都在保留内存一样。
【问题讨论】:
-
我认为您假设流是问题所在,而且可能是错误的。这些字符串有多大?如果它们是在 LOH 上分配的,那么您可能会导致大量碎片。使用分析器查看内存分配的位置。
-
GC.Collect() 在这些情况下可能会有所帮助,或者为 64 位编译应用程序。尽管即使在 32 位上,如果内存压力过高,GC 也会自动运行。也许对象太大了,它们会放在大对象堆上?
-
获取内存分析器并使用它来确定内存中的内容。我们无法知道您的机器上发生了什么。
-
我遵循@Eric Lippert 和 Ed S. 的建议并使用分析器进行了检查,它确实是导致问题的流阅读器。现在我需要找到一种方法,从我停止使用新的流读取器对象的地方开始。谢谢大家。
-
如果您遇到内存问题,请转储 DataTable - 它会占用内存。到目前为止,.NET 中的集合已经出现。我不了解 Oracle,但在 MSSQL 中,我使用 TVP(表值参数)获得了最快的上传,我将它们与集合(HashTable)而不是 DataTable 一起使用。它就像一个引用 DataReader。我解析一些文本文件并加载单词并每晚加载数百万。我在主线程上解析,然后每 10,000 行使用 BackGround 工作线程加载到另一个线程上的 SQL。
标签: c# dispose out-of-memory