31

アプリケーションを構築していて、データベースへの1回のラウンドトリップに複数のクエリをバッチ処理したいと考えています。たとえば、1つのページにユーザーのリスト、グループのリスト、および権限のリストを表示する必要があるとします。

だから私はprocs(または "select * from Users"のような単純なSQLコマンド)を保存しました、そしてそれらのうちの3つを実行したいと思います。ただし、この1ページにデータを入力するには、3回往復する必要があります。

これで、単一のストアドプロシージャ( "getUsersTeamsAndPermissions")を作成するか、単一のSQLコマンド "select * from Users; exec getTeams; select *fromPermissions"を実行できます。

しかし、1回の往復で3つの操作を実行するように指定するより良い方法があるかどうか疑問に思いました。利点には、単体テストが容易になることや、データベースエンジンがクエリを並列化できることが含まれます。

C#3.5とSQLServer2008を使用しています。

4

6 に答える 6

38

このようなもの。この例は、オブジェクトを適切に破棄していないため、おそらくあまり良くありませんが、アイデアは得られます。クリーンアップされたバージョンは次のとおりです。

using (var connection = new SqlConnection(ConnectionString))
using (var command = connection.CreateCommand())
{
    connection.Open();
    command.CommandText = "select id from test1; select id from test2";
    using (var reader = command.ExecuteReader())
    {
        do
        {
            while (reader.Read())
            {
                Console.WriteLine(reader.GetInt32(0));
            }
            Console.WriteLine("--next command--");
        } while (reader.NextResult());

    }
}
于 2010-02-25T18:01:29.857 に答える
9

あなたが言及する単一のマルチパートコマンドとストアドプロシージャオプションは2つのオプションです。データベースで「並列化」されるような方法でそれらを行うことはできません。ただし、これらのオプションは両方とも1 回の往復になるので、問題ありません。それらをより効率的に送信する方法はありません。SQL Server 2005 以降では、完全にパラメータ化されたマルチパート コマンドが非常に効率的です。

編集: 1 回の呼び出しに詰め込む理由に関する情報を追加します。

通話を減らすことはあまり気にしたくありませんが、これに正当な理由がある場合があります。

  • 私はかつて、メインフレームに対して厄介な ODBC ドライバーに制限されていました。呼び出しごとに 1.2 秒のオーバーヘッドがありました。私は真剣です。db 呼び出しに少し余分に詰め込むことがありました。かわいくない。
  • また、SQL クエリをどこかで設定しなければならない状況に陥るかもしれませんが、呼び出しを 3 つだけ行うことはできません。呼び出しは 1 つでなければなりません。そうであってはなりません、悪いデザインですが、そうです。あなたはあなたがしなければならないことをします!
  • もちろん、複数のステップをストアド プロシージャにカプセル化すると非常に便利な場合もあります。通常はラウンドトリップを節約するためではありませんが、よりタイトなトランザクション、新しいレコードの ID の取得、アクセス許可の制約、カプセル化の提供、何とか何とか。
于 2010-02-25T18:04:08.463 に答える
2

1回の往復と3回の往復のほうが効率的です。問題は、苦労する価値があるかどうかです。ADO.Net と C# 3.5 のツールセットとフレームワーク全体が、ユーザーの試みに反対しています。TableAdapters、Linq2SQL、EF、これらはすべて、単純な one-call==one-resultset セマンティクスを処理するのが好きです。そのため、フレームワークを打ち負かして提出しようとすると、深刻な生産性が失われる可能性があります。

往復回数を減らす必要があることを示す重大な測定値がない限り、控えてください。これが必要になった場合は、ストアド プロシージャを使用して、少なくとも API の種類のセマンティクスを提供します。

しかし、クエリが実際に投稿したものである場合 (つまり、すべてのユーザー、すべてのチーム、およびすべての権限を選択する)ラウンドトリップ減らす前に揚げるべきはるかに大きな魚が明らかにあります...最初に結果セットを減らします。

于 2010-02-25T18:06:14.340 に答える
1

このリンクが役立つかもしれません

少なくとも同じ接続開始を使用することを検討してください。hereの内容によると、接続を開くことは、Entity-Framework のパフォーマンス コストのトップ リーダーです。

于 2010-11-30T12:12:26.207 に答える
0

一時テーブルを作成しますか? すべての結果を一時テーブルに挿入してからselect * from @temp-table

のように、

@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2

など...データベースへのアクセスは1回だけですが、実際により効率的かどうかはわかりません。

于 2010-02-25T18:05:56.587 に答える
0

まず、3往復は大したことではありません。300回のラウンドトリップについて話している場合、それは別の問題になりますが、わずか3回のラウンドトリップの場合、これは時期尚早の最適化のケースであると断言できます.

そうは言っても、私がこれを行う方法は、おそらく SQL を使用して 3 つの格納されたプロシージャーを実行することです。

exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2
exec dbo.p_myproc_2
exec dbo.p_myproc_3

複数の行セットを直接実行した場合と同様に、返された結果セットを反復処理できます。

于 2010-02-25T18:11:44.853 に答える