尝试通过StreamReader将800MB文本文件加载到DataTable时,我遇到了OutOfMemory Exceptions.我想知道是否有办法从内存流中批量加载DataTable,即从StreamReader读取文本文件的前10,000行,创建DataTable,使用DataTable执行某些操作,然后将下10,000行加载到StreamReader中等等.
我的谷歌在这里不是很有帮助,但似乎应该有一个简单的方法来做到这一点.最后,我将使用SqlBulkCopy将DataTables写入MS SQL数据库,因此如果有一种比我描述的更简单的方法,我会感谢快速指向正确的方向.
编辑 - 这是我正在运行的代码:
public static DataTable PopulateDataTableFromText(DataTable dt, string txtSource)
{
StreamReader sr = new StreamReader(txtSource);
DataRow dr;
int dtCount = dt.Columns.Count;
string input;
int i = 0;
while ((input = sr.ReadLine()) != null)
{
try
{
string[] stringRows = input.Split(new char[] { '\t' });
dr = dt.NewRow();
for (int a = 0; a < dtCount; a++)
{
string dataType = dt.Columns[a].DataType.ToString();
if (stringRows[a] == "" && (dataType == "System.Int32" || dataType == "System.Int64"))
{
stringRows[a] = "0";
}
dr[a] = Convert.ChangeType(stringRows[a], dt.Columns[a].DataType);
}
dt.Rows.Add(dr);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
i++;
}
return dt;
}
Run Code Online (Sandbox Code Playgroud)
这是返回的错误:
"System.OutOfMemoryException:类型'System.OutOfMemoryException'的异常被抛出.
在System.String.Split(Char []分隔符,Int32计数,StringSplitOptions选项)
处于System.String.Split(Char [] separator}
处于Harvester.Config .PopulateDataTableFromText(DataTable dt,String txtSource)在C:...."
关于将数据直接加载到SQL中的建议 - 当谈到C#时,我有点像菜鸟,但我认为这基本上就是我在做什么?SqlBulkCopy.WriteToServer获取我从文本文件创建的DataTable并将其导入sql.有没有更容易的方法来做到这一点,我错过了?
编辑:哦,我忘了提 - 这段代码不会在与SQL Server相同的服务器上运行.数据文本文件位于服务器B上,需要写入服务器A中的表.是否排除使用bcp?
您是否考虑过将数据直接加载到SQL Server中,然后在数据库中对其进行操作?数据库引擎已经设计为以有效的方式执行大量数据的操作.这可能会产生更好的整体结果,并允许您利用数据库和SQL语言的功能来完成繁重的工作.这是旧的"更聪明,更努力"的原则.
有许多不同的方法可以将数据加载到SQL Server中,因此您可能需要检查这些方法以查看是否适合.如果您使用的是SQLServer 2005或更高版本,并且您确实需要对C#中的数据进行一些操作,则可以始终使用托管存储过程.
这里需要注意的OutOfMemoryException是,这有点误导.内存不仅仅是你拥有的物理内存量.你可能耗尽的是可寻址的内存.这是一个非常不同的事情.
将大文件加载到内存并将其转换为内存时,DataTable可能需要的不仅仅是800Mb来表示相同的数据.由于32位.NET进程仅限于2Gb的可寻址内存,因此您可能永远无法在一个批处理中处理此数量的数据.
您可能需要做的是以流方式处理数据.换句话说,不要尝试将其全部加载DataTable到SQLServer中然后批量插入.而是以块的形式处理文件,一旦完成它们就清除先前的行集.
现在,如果您可以访问具有大量内存的64位计算机(以避免VM抖动)和64位.NET运行时的副本,那么您可以在不更改的情况下运行代码.但我建议做出必要的改变,因为它甚至可以在那种环境下提高性能.
| 归档时间: |
|
| 查看次数: |
6418 次 |
| 最近记录: |