有没有更快的方法从数据库查询中填充结果集?

时间:2011-07-08 05:01:02

标签: c# performance datatable sybase-iq

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

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行。以下是此次电话会议内部网络内容的详情:

enter image description here

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

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

我建议使用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; 
    }

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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