我正在将csv数据从文件加载到数据表中进行处理。
问题是,我想处理几个文件,而我对数据表的测试显示了巨大的内存消耗我用一个37MB的csv文件进行了测试,内存增长到240MB,这相当于IMHO。我读到,数据表中有开销,我可以使用大约70MB的大小,但不能使用240MB,这意味着它是原始大小的六倍。我在这里读到,数据表比POCO需要更多的内存,但区别太大了。
我安装了一个内存探查器,查看是否存在内存泄漏以及内存在哪里。我发现,datatablecolumns中有6MB到19MB的字符串,datatable中大约有20列。值是否存储在列中?为什么占用了这么多内存,我能做些什么来减少内存消耗。由于内存消耗,数据附件似乎无法使用。
是否有其他人对数据表有这样的问题,或者我做错了什么?
PS:我尝试了一个70MB的文件,数据表增长到了500MB!
好的,这里是一个小的测试用例:37MB的csv文件(21列)使内存增加到179MB。
private static DataTable ReadCsv()
{
DataTable table = new DataTable();
table.BeginLoadData();
using (var reader = new StreamReader(File.OpenRead(@"C:DevelopTestscsv-Datatestdatentest.csv")))
{
int y = 0;
int columnsCount = 0;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
if (y == 0)
{
columnsCount = values.Count();
// create columns
for (int x = 0; x < columnsCount; x++)
{
table.Columns.Add(new DataColumn(values[x], typeof(string)));
}
}
else
{
if (values.Length == columnsCount)
{
// add the data
table.Rows.Add(values);
}
}
y++;
}
table.EndLoadData();
table.AcceptChanges();
}
return table;
}
DataSet
及其子级DataTable
、DataRow
等组成内存中的关系数据库。这涉及到很多开销(尽管它确实让[一些]事情变得非常方便
如果内存有问题,
- 构建域对象,用键入的属性表示CSV文件中的每一行
- 创建一个自定义集合(或者只使用
IList<T>
来保存它们 - 或者,使用
DataTable
的基本语义构建一个轻量级类:- 按数字选择行的能力
- 能够逐行选择一行中的一列,也可以选择列名或编号
- 了解有序列名集的能力
- 附加功能:能够按名称或序号选择列,并接收其值列表,每行一个
您确定需要CSV文件的内存表示形式吗?你能像Sebastien Lorion的快速CSV阅读器一样通过IDataReader
访问它们吗?
DataTables是将表格数据放入内存并添加许多与表相关的功能的通用解决方案。如果开销对您来说是不可接受的,您可以选择1)编写自己的DataTable类,以消除不需要的开销2)使用仍然可以完成所需内容的替代表示,可能是基于POCO的,也可能是XMLDocument(可能有同样多的开销,可能更多,从来没有真正担心过)。3) 不要试图将所有内容加载到内存中,只需根据需要从外部存储中引入数据即可。