19

System.Data.SqlClient.SqlCommandSQL Server Management Studioから実行する場合(2分後にタイムアウト)よりもはるかに高速に実行されるストアドプロシージャがあります(2秒)。

これの理由は何でしょうか?


詳細:SQL Server Management Studioでは、これは2秒で実行されます(本番データベースで):

EXEC sp_Stat
    @DepartmentID = NULL

.NET / C#では、2分後に次のタイムアウトが発生します(本番データベースの場合)。

string selectCommand = @"
EXEC sp_Stat
    @DepartmentID = NULL";
string connectionString = "server=***;database=***;user id=***;pwd=***";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlCommand command = new SqlCommand(selectCommand, connection))
    {
        connection.Open();
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
            }
        }
    }
}

、、、も試してみましたがselectCommand = "sp_Stat"、同じ結果です。CommandType = StoredProcedureSqlParameter

そしてそれEXECがなければ、同じ結果になります。

ほとんどデータが空の開発データベースでは、どちらの場合も1秒未満で終了します。つまり、データベースには大量のデータがあることに関連していますが、それは.NETからのみ発生するようです...


Marc GravellがさまざまなSET値について書いたことは、提示されたケースに違いをもたらします。

SQL Server Profilerは、Sql Server Management Studioが、SET.NETSqlクライアントデータプロバイダーが実行しない次のを実行することを示しました。


SET ROWCOUNT 0 
SET TEXTSIZE 2147483647 
SET NOCOUNT OFF 
SET CONCAT_NULL_YIELDS_NULL ON 
SET ARITHABORT ON 
SET LOCK_TIMEOUT -1 
SET QUERY_GOVERNOR_COST_LIMIT 0 
SET DEADLOCK_PRIORITY NORMAL 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
SET ANSI_NULLS ON 
SET ANSI_NULL_DFLT_ON ON 
SET ANSI_PADDING ON 
SET ANSI_WARNINGS ON 
SET CURSOR_CLOSE_ON_COMMIT OFF 
SET IMPLICIT_TRANSACTIONS OFF 
SET QUOTED_IDENTIFIER ON
SET NOEXEC, PARSEONLY, FMTONLY OFF

これらを含めると、SSMSと.NETで同じクエリに同じ時間がかかりました。そして責任SETは...

SET ARITHABORT ON

私は何を学びましたか?推測する代わりにプロファイラーを使用するかもしれません...

(最初の解決策は、パラメーターのスニッフィングに関連しているように見えました。しかし、私はいくつかのことを混ぜ合わせていました...)

4

4 に答える 4

11

重要になる可能性のあるもう1つのことはSET有効になっているオプションです。これらのオプションの一部は、プロファイルを変更するのに十分なクエリプランを変更します。(たとえば)計算された+永続化された(場合によってはインデックス付けされた)列を見ている場合、いくつかは大きな影響を与える可能性があります。SETオプションに互換性がない場合、インデックス付けされたものを使用するのではなく、値を再計算するように強制される可能性があります値-インデックスシークをテーブルスキャン+計算に変更できます。

プロファイラーを使用して、どのSETオプションが「機能している」かを確認し、それらのオプションを使用すると状況が変わるかどうかを確認してください。

もう1つの影響は、接続文字列です。たとえば、動作を微妙に変更できるMARSを有効にした場合です。

最後に、トランザクション(暗黙的(TransactionScope)または明示的)は、分離レベルに応じて大きな影響を与える可能性があります。

于 2009-04-29T11:56:14.900 に答える
5

これはほぼ間違いなく、「誤った」キャッシュクエリプランが原因です。これはSOで何度も出てきました。

最新の統計はありますか?定期的なインデックス保守計画?

これをストアドプロシージャ定義に追加することで、キャッシュされたクエリプランが原因であるかどうかをテストできます。

CREATE PROCEDURE usp_MyProcedure WITH RECOMPILE...

これにより、データベース全体のインデックスが再作成されます(データベースが非常に大きい場合は注意してください)。

exec sp_msforeachtable "dbcc dbreindex('?')"

SOの投稿:

ManagmentStudioとTableAdapterのストアドプロシージャの実行時間に大きな違いがあります。

SQL Serverでのパラメータスニッフィング(またはなりすまし)

SQL Server 2005の不明を最適化しますか?

同じストアドプロシージャの異なる実行プラン

于 2009-04-29T11:35:12.987 に答える
1

同様の問題があり、接続文字列にMultipleActiveResultSets = trueが含まれていると(影響が最小限であると想定されます)、リモート接続を介した1.5milレコードのプルに約2分ではなく25分かかることが判明しました。

于 2016-07-28T03:43:40.970 に答える
0

同様の問題が発生しました。クエリはSSMSで2秒で完了し、.NETクライアントから呼び出されると90秒以上かかります(テスト用にいくつかのVB / C#アプリ/サイトを作成しました)。

クエリプランが異なるのではないかと考え、明示的なループ(「内部ループ結合」と「インデックス付き」)のヒントを使用してクエリを書き直しました。これで問題は解決しました。

于 2009-04-29T11:30:44.010 に答える