SqlDataReader性能列表<string []>或List <object []>

Cha*_*ams 7 c# performance sqldatareader

我一直在尝试尽快从SQL服务器读取数据的方法,我遇到了一个有趣的发现.如果我将数据读入List<object[]>而不是a List<string[]>,则性能会提高一倍以上.

我怀疑这是因为不必ToString()在字段上调用方法,但我一直认为使用对象会对性能产生负面影响.

有没有理由不使用对象数组列表而不是字符串数组?

编辑:我只想到了这个数据的存储大小.将数据存储在对象数组中会比字符串占用更多空间吗?

这是我的测试代码:

private void executeSqlObject()
    {
        List<object[]> list = new List<object[]>();

        using (SqlConnection cnn = new SqlConnection(_cnnString))
        {
            cnn.Open();
            SqlCommand cmd = new SqlCommand("select * from test_table", cnn);

            SqlDataReader reader = cmd.ExecuteReader();

            int fieldCount = reader.FieldCount;

            while (reader.Read())
            {
                object[] row = new object[fieldCount];

                for (int i = 0; i < fieldCount; i++)
                {
                    row[i] = reader[i];
                }
                list.Add(row);
            }
        }
    }

    private void executeSqlString()
    {
        List<string[]> list = new List<string[]>();

        using (SqlConnection cnn = new SqlConnection(_cnnString))
        {
            cnn.Open();
            SqlCommand cmd = new SqlCommand("select * from test_table", cnn);

            SqlDataReader reader = cmd.ExecuteReader();

            int fieldCount = reader.FieldCount;

            while (reader.Read())
            {
                string[] row = new string[fieldCount];

                for (int i = 0; i < fieldCount; i++)
                {
                    row[i] = reader[i].ToString();
                }
                list.Add(row);
            }
        }
    }

    private void runTests()
    {
        Stopwatch watch = new Stopwatch();
        for (int i = 0; i < 10; i++)
        {
            watch.Start();
            executeSqlObject();
            Debug.WriteLine("Object Time: " + watch.ElapsedMilliseconds.ToString());
            watch.Reset();
        }
        for (int i = 0; i < 10; i++)
        {
            watch.Start();
            executeSqlString();
            Debug.WriteLine("String Time: " + watch.ElapsedMilliseconds.ToString());
            watch.Reset();
        }
    }
Run Code Online (Sandbox Code Playgroud)

结果如下:

Object Time: 879
Object Time: 812
Object Time: 825
Object Time: 882
Object Time: 880
Object Time: 905
Object Time: 815
Object Time: 799
Object Time: 823
Object Time: 817
Average: 844

String Time: 1819
String Time: 1790
String Time: 1787
String Time: 1856
String Time: 1795
String Time: 1731
String Time: 1792
String Time: 1799
String Time: 1762
String Time: 1869
Average: 1800
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 8

object如果你造成额外的拳击,只会增加开销.即便如此,这种影响相当小.在您的情况下,reader[i] 总是返回object.object无论是对字符串的引用,还是int等,你已经拥有它了.当然,调用.ToString()增加了开销; 在大多数情况下(int,DateTime等),这涉及格式化代码一个(或多个)额外字符串的分配.通过更改为string您正在更改数据(更糟糕的是,IMO - 例如,您不能再对日期执行正确的排序)并增加开销.这里的边缘情况是,如果所有列都已经是实际的字符串 - 在这种情况下,您只需添加一些虚拟方法调用(但没有额外的实际工作).

有关信息,如果您在原始性能之后,我完全建议您查看微型ORM,例如dapper.它们经过了大量优化,但避免了"完整"ORM的重量.例如,在精致:

var myData = connection.Query<TypedObject>("select * from test_table").ToList();
Run Code Online (Sandbox Code Playgroud)

我希望,在给你强类型的对象数据时,它会表现得非常可比.