【问题标题】:is there any faster way to populate a resultset from a database query?有没有更快的方法从数据库查询中填充结果集?
【发布时间】:2011-07-08 13:33:13
【问题描述】:

我有以下代码查询数据库并填充数据表。

private DataTable Run(string sql)
    {
        var conn = new OdbcConnection();

        string connString = "[myConnString];";

        conn.ConnectionString = connString;
         conn.Open();

        var da = new OdbcDataAdapter {SelectCommand = conn.CreateCommand()};
        da.SelectCommand.CommandText = sql;
        var dt = new DataTable();
        da.Fill(dt);
        da.Dispose();
        conn.Close();

        return dt;
    }

我刚刚在它上面运行了一个分析器,它显示这条线需要很长时间:

 da.Fill(dt);

查询仅返回大约 1000 行。以下是此次通话中 .net 内部发生的情况的详细资料:

鉴于我正在运行查询,将其转换为数据表,然后将该表转换为对象列表,下面有什么可以优化的吗(以某种方式直接从数据适配器转换为对象列表??)。我基本上是在寻找解决此代码中此性能瓶颈的方法?

【问题讨论】:

  • 这 10 秒中有多少只是接收数据的时间?不加载数据表,只是 getting 它。问题可能不是代码,可能是数据库、网络等。

标签: c# performance datatable sap-iq


【解决方案1】:

我认为确保您的查询快速运行就是答案。代码不能更快,但优化查询可以产生巨大的差异。您可以使用 SQL 分析器检查原始 SQL 查询的执行情况吗?

例如添加数据库索引或返回更少的列。网络延迟也可能导致缓慢。数据库与代码执行是否在同一个局域网?

【讨论】:

    【解决方案2】:

    我建议使用 OdbcDataReader 和 Transform 函数。像下面这样的东西应该可以工作:

    public class OdbcQuery
    {
        OdbcCommand Command { get; set; }
    
        public OdbcQuery(OdbcConnection connection, string cmdText)
        {
            Command = new OdbcCommand(cmdText, connection); 
        }
    
        public List<T> Transform<T>(Func<OdbcDataReader, T> transformFunction)
        {
            Command.Connection.Open();
    
            OdbcDataReader reader = Command.ExecuteReader(CommandBehavior.Default);
    
            List<T> tList = new List<T>();
    
            while (reader.Read())
            {
                tList.Add(transformFunction(reader));
            }
    
            Command.Connection.Close();
    
            return tList; 
        }
    }
    

    这是一个示例转换函数,它将为查询中的每一行创建一个类型为 T 的实例。在这种情况下,它只是一个 Foo 对象,

    public class Foo
    {
        public Foo() { }
    
        public string FooString { get; set; }
        public int FooInt { get; set; }
    }
    
    class Program
    {
        public static List<Foo> GetFooList(string connectionString, string cmdText)
        {
            OdbcQuery query = new OdbcQuery(new OdbcConnection(connectionString), cmdText);
    
            List<Foo> fooList = query.Transform(
                rdr =>
                {
                    Foo foo = new Foo();
    
                    foo.FooInt = rdr.GetInt32(0);
                    foo.FooString = rdr.GetString(1); 
    
                    return foo; 
                });
    
            return fooList; 
        }
    

    这应该表现良好,因为您的特定领域对象是在第一次循环通过数据库结果时创建的,不需要第二或第三个翻译阶段。

    【讨论】:

    • 谢谢..我转换为使用上面的代码。虽然它为什么比我上面所做的更有效是有道理的,但在对其进行分析(使用 dottrace)之后,总体时间几乎相同
    【解决方案3】:

    如果您正在寻找速度,请不要使用数据集/数据适配器,它们是一种旧技术,不是为速度而构建的。 使用 Sean 建议的数据阅读器。

    【讨论】:

      【解决方案4】:

      除了 DataReader,您还可以检查您的查询是否设计良好。

      也许您可以对其进行优化或将其拆分为多个并行操作

      【讨论】:

        猜你喜欢
        • 2021-07-24
        • 1970-01-01
        • 2016-03-12
        • 1970-01-01
        • 2014-01-05
        • 2014-07-29
        • 2010-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多