3

dbをクエリし、データテーブルにデータを入力する次のコードがあります。

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内で行われていることのプロファイルの詳細は次のとおりです。

ここに画像の説明を入力してください

クエリを実行し、それをデータテーブルに変換してから、そのテーブルをオブジェクトのリストに変換することを考えると、これを最適化するためにできることは以下にあります(データアダプタからオブジェクトのリストに直接変換する方法はありますか??) 。私は基本的に、このコードでこのパフォーマンスのボトルネックの回避策を探していますか?

4

4 に答える 4

2

クエリがすばやく実行されるようにすることが答えだと思います。コードをこれほど速くすることはできませんが、クエリを最適化することで大きな違いが生まれます。SQLプロファイラーを使用して、生のSQLクエリの実行を確認できますか?

たとえば、データベースインデックスを追加したり、返す列の数を減らしたりします。ネットワーク遅延も速度低下の原因となる可能性があります。コードが実行されているのと同じLAN上のデータベースですか?

于 2011-07-08T05:10:39.887 に答える
1

Transform関数と一緒にOdbcDataReaderを使用することをお勧めします。次のようなものが機能するはずです。

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番目または3番目の変換フェーズは必要ありません。

于 2011-07-08T05:27:11.797 に答える
0

速度を求めている場合は、データセット/データアダプターを使用しないでください。これらは、速度を重視して構築されていない古いテクノロジーです。ショーンが提案したようなデータリーダーを使用してください。

于 2011-07-08T05:29:47.123 に答える
0

DataReaderに加えて、クエリが適切に設計されているかどうかを確認できます。

おそらく、それを最適化するか、イベントを複数の並列アクションに分割することができます

于 2011-07-08T05:33:13.990 に答える