在.NET DataTable中存储数据的内存开销是多少?

时间:2009-01-08 15:18:16

标签: .net datatable memory-management

我正在尝试处理与.NET DataTable相关的内存开销量,以及表中的单个DataRows。
换句话说,数据表占用的内存多于存储每列数据的正确类型数组所需的内存量?
我想会有一些基本的表开销,加上每列的一些数量,然后每行再增加一个数量。

所以有人可以对这三种开销中的每一种/任何一种进行估算(并且,我猜,解释!)?

3 个答案:

答案 0 :(得分:22)

好吧,不要忘记DataTable存储2个? 3?数据的版本 - 原始和更新(可能是另一个?)。它也有很多引用,因为它是基于单元格的,以及任何值类型的装箱。很难量化准确的记忆......

就我个人而言,我很少使用DataTable - 类型的POCO课程在我看来是一个更明智的选择。我不会使用数组(直接),但是List<T>BindingList<T>或类似会更常见。

作为一个粗略的衡量标准,你可以创建很多表等,并查看内存使用情况;例如,以下显示了~4.3因子 - 即超过4倍的成本,但显然这在很大程度上取决于列数与行与表等的比较:

    // takes **roughly** 112Mb  (taskman)
    List<DataTable> tables = new List<DataTable>();
    for (int j = 0; j < 5000; j++)
    {
        DataTable table = new DataTable("foo");
        for (int i = 0; i < 10; i++)
        {
            table.Columns.Add("Col " + i, i % 2 == 0 ? typeof(int)
                                : typeof(string));
        }
        for (int i = 0; i < 100; i++)
        {
            table.Rows.Add(i, "a", i, "b", i, "c", i, "d", i, "e");
        }
        tables.Add(table);
    }
    Console.WriteLine("done");
    Console.ReadLine();

VS

    // takes **roughly** 26Mb (taskman)
    List<List<Foo>> lists = new List<List<Foo>>(5000);
    for (int j = 0; j < 5000; j++)
    {
        List<Foo> list = new List<Foo>(100);
        for (int i = 0; i < 100; i++)
        {
            Foo foo = new Foo { Prop1 = "a", Prop3 = "b",
                 Prop5 = "c", Prop7 = "d", Prop9 = "e"};
            foo.Prop0 = foo.Prop2 = foo.Prop4 = foo.Prop6 = foo.Prop8 = i;
            list.Add(foo);
        }
        lists.Add(list);
    }
    Console.WriteLine("done");
    Console.ReadLine();

(基于)

class Foo
{
    public int Prop0 { get; set; }
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
    public string Prop3 { get; set; }
    public int Prop4 { get; set; }
    public string Prop5 { get; set; }
    public int Prop6 { get; set; }
    public string Prop7 { get; set; }
    public int Prop8 { get; set; }
    public string Prop9 { get; set; }
}

答案 1 :(得分:8)

如果不在列上定义索引,则开销很低。如果使用字符串缓存,则可以获得相当低的内存占用: 使用HashSet或Dictionary仅使用每个字符串值的1个字符串实例。这听起来很奇怪,但如果从数据库中获取数据,并且您有多个具有相同字符串值的行(例如“ALFKI”),则字符串值相等,但字符串实例不相同:字符串存储多次记忆。如果您首先使用HashSet过滤掉重复的实例,则可以在数据表的任何位置有效地使用相同的字符串实例作为1个字符串值。这可以大大减少内存占用。当然,如果字符串值已经在某处静态定义(因此不能从外部源读取),则不值得付出努力。

答案 2 :(得分:4)

这取决于您存储的数据量和数据类型。显然数据越多,内存越多。数据表存在一些开销,这使得它更加昂贵。您还需要了解大对象堆。如果存储的对象超过85 kb,则对象将存储在LOH中。这可能会对您的垃圾收集造成严重破坏,因为它需要完整的收集。如果您正在测试它,请查看内存分析器以观察数据表的内存占用。