使用比DataTable更多的内存列出<object []>?</object []>

时间:2009-11-20 17:31:56

标签: c# datatable ado.net

我一直认为DataTable会消耗比通用List更多的内存。我正在测试加载DataTable并从SQL Server查询加载List。在这种情况下,DataTable消耗的内存较少。我得到了前2000行,每行有134个字段。一个二进制字段,其余为标准varchar,int,bit等。

如果DataTable的所有开销都比List更少,那么它在世界上会有多少? GC使用DataTable报告大约4mb,使用列表报告5mb。

我用一些NorthWind表进行了测试,在这些情况下,列表略小一些。

private void GetMemory()
    {
        label1.Text = string.Format("{0:0.00} MB", GC.GetTotalMemory(true) / 1024.0 / 1024.0);            
    }
    private void DataTableButton_Click(object sender, EventArgs e)
    {
        var conn = new SqlConnection(@"Initial Catalog=ADatabase;Data Source=AServer;Integrated Security=True");
        conn.Open();

        var cmd = new SqlCommand("SELECT TOP 2000 * FROM AManyColumnedTable", conn);

        var r = cmd.ExecuteReader();
        _rows = new List<object[]>();

        //uses more memory
        object[] a = null;
        while (r.Read())
        {
            a = new object[r.FieldCount];
            r.GetValues(a);
            _rows.Add(a);
        }
        //uses less memory
        //_table = new DataTable("TheTable");
        //_table.Load(r);

        r.Close();
        conn.Close();
        GetMemory();
    }

3 个答案:

答案 0 :(得分:4)

这是一种幻觉。不知何故GC没有给你正确的值,也许是因为有些对象尚未收集。也许加载数据表会导致更多的中间对象,从而导致另一次垃圾收集。

您的数组列表以与数据表相同的方式存储数据,但没有数据表和每个数据行包含的额外信息的开销。

如果希望它的内存效率更高,则应为数据记录创建一个类,这样您就可以将值类型存储为普通值而不是在对象中装箱。例如,一个int在装箱时使用20个字节,但只有4个作为普通成员变量。

答案 1 :(得分:1)

出于好奇,尝试在List上调用TrimExcess,然后检查内存。我怀疑这会产生很大的不同,但我怀疑它会有所不同。

基本上,List会分批增长。每次添加对象时它都不会增长,而是增加一定量,然后如果它需要更多,它会分配更多。我很好奇你的列表中是否有一些你没有使用的额外空间。

答案 2 :(得分:0)

对我来说,它恰好相反。好吧,我没有从数据库中获取数据,而是使用批量插入将数据推送到数据库。在处理数据时,我获得了大约5000万条记录作为输出,我想将其存储到数据库中。我使用DataTable(只有8列)使用每次推送200k行的批量插入,并发现每次插入时平均需要大约95 MB的数据(使用网络监视工具和序列化器来查找对象的大小)。当我使用List(使用IDataReader)进行批量插入时,它将(一次推送)推送的大小降低到15 MB平均值(使用序列化来查找对象的大小并在任务管理器中监视)。使用DataTable处理和上传数据所需的时间为1657秒,使用List方法将其降至850秒。