8

.NETからSQLServerのsp_executesqlストアドプロシージャへの呼び出しを実行しているORMを使用しています。

ストアドプロシージャが.NETから呼び出されると、タイムアウト例外が発生します。

プロファイラーを見ると、クエリの実行に実際に長い時間がかかっていることがわかります。

クエリは基本的に次のとおりです。

exec sp_executesql N'SELECT DISTINCT
FROM [OurDatabase].[dbo].[Contract] [LPLA_1] ) [LPA_L1]
LEFT JOIN [OurDatabase].[dbo].[Customer] [LPA_L2]  ON [LPA_L2].[Customer_ID]=[LPA_L1].[CustomerId] AND [LPA_L2].[Data]=[LPA_L1].[Data])
WHERE ( ( ( ( ( [LPA_L1].[DealerId] = @DealerId1)) 
AND ( [LPA_L2].[Last_Name] = @LastName2))))',N'@DealerId1 varchar(18),@LastName2 varchar(25)',@DealerId1='1234',@LastName2='SMITH'

私にとって紛らわしい部分は次のとおりです。タイムアウトしたクエリをコピーしてSQLManagementStudioに貼り付け、インタラクティブに実行すると、問題なく実行されます。

.NETコードを介して実行した場合に同じクエリに大幅に時間がかかる理由を誰かが知っていますか?(私はこれを再現することができます-コードから実行されたクエリは一貫してタイムアウトし、インタラクティブに実行されたクエリは一貫して正常に機能します。)

どんな助けでも大歓迎です。ありがとう!

4

6 に答える 6

4

One thing I've seen a few times is if you have a mismatch between nvarchar and varchar types for a query parameter on an indexed field. This can happen if you use varchar in your database and don't explicitly set the type of your parameter in .Net, which will assume nvarchar by default.

In that case, Sql Server chooses the more correct option rather than the better performing option. Rather than just convert your parameter to varchar, which would be a narrowing conversion that could potentially lose information, the database will be forced to convert every value for that column in the table to an nvarchar (which is guaranteed to succeed without loss of information). Not only is that slow, but Sql Server won't be able to use the index any more. Needless to say, the query will take much longer to run.

于 2009-10-02T13:46:51.463 に答える
1

sp_executelsqlはコンパイルされたクエリプランを再利用することを目的としているため、同じクエリが再度ヒットしたときにパラメータを再スニッフィングしないため、非常に遅いプランを使用することになります(理由がわかります現在のパラメータ値を使用した(より遅いクエリプラン)。sp_executesqlはインデックスを選択するために異なる方法を使用しているようであり、プレーンテキストクエリと比較して明らかに壊れた方法です。

異なるのは、sp_executesqlの下の'Company(a table)'のテーブル更新は、ネストされたループのチェーンを介して供給され、テキストクエリはハッシュマッチのチェーンを介して供給されることです。ビューの構成は、2つのバージョン間で同じように見えます(これは私が期待していることです)。残念ながら、残りは非常に複雑で、途中で根本的に異なることをしているように見えます。「実際の」実行プランを取得しても、クエリのさまざまなサブコンポーネントの実際の実行時間はわかりません。実際、sp_executesqlが別の方法で何かを選択する理由はわかりませんが、非常に遅い計画を確実に構築します。

パラメータスニッフィングはこれに対する解決策であるため、パラメータ名の名前を変更するか、where句の列名を入れ替えて、sp_executesqlが古い低速プランを使用する代わりにクエリプランを再作成するようにすることもできます。もちろん、これは解決策ではありませんが、遅いプランをそれほど長くキャッシュすることはありません。

よろしく。

于 2012-06-19T11:41:17.950 に答える
1

同じ問題がありました。

インデックスを再構築することで問題が解決しました。

おそらく問題は、パラメーターの型が nvarchar であるのに対して、varchar 列にあるインデックスにあるということです...?

于 2010-12-01T15:04:32.200 に答える
1

これが私が見つけたものです。私は非常に複雑なストアド プロシージャを持っています。これは常に情報をカウントし、データを 8 列 17 行のマトリックスに入れます。これは、Crystal Reports によって毎月呼び出されたり実行されたりします。prod データベースは、96 GB の非常に高速なサーバー上にありました。最近、32 GB の仮想マシンに縮小されました。スケールダウンしている間、いくつかのインデックスが追加されるまで、多くの点でアプリの実行が遅くなりました。

そして、この 17 行のマトリックスの月次レポートを実行する時間になりました...そして、ご想像のとおり、タイムアウトになりました。

proc 呼び出しは非常に単純で、3 つのパラメーターがありました。開始日、終了日、およびフィルタリングする地区 - null はすべてに等しい。2 つの日付は Crystal Reports から文字として渡され、これらの保存された PROC パラメータは、このクレイジーな保存された proc のいたるところで使用されました。

17 行のそれぞれ - 基本的に WITH ステートメントとクレイジーな結合を使用して、結果をカウント/ピボットする前にデータの行を検索します...これは、この記事では重要ではありません。

ここでは簡略化します....

CREATE PROCEDURE [dbo].[prcMonthlyStats]
@bDate          datetime
,@eDate         datetime
,@districtStr   varchar(120)
AS
BEGIN
SET NOCOUNT ON;

...

--the @bDate and @eDate params were DIRECTLY used throughout the 2000 lines of SQL,
--to filter data inside and out of WITH statements and various other selects!
--
--TIMES OUT!

...

CREATE PROCEDURE [dbo].[prcMonthlyStats]
@bDateStr       datetime
,@eDateStr      datetime
,@districtStr   varchar(120)
AS
BEGIN
SET NOCOUNT ON;

--FIX!  Declare 2 date time variables and simply assign the 2 date time parameters to them.
DECLARE @bDate      datetime
DECLARE @eDate      datetime
DECLARE @district   varchar(120)

--SET THE VARIABLES FROM THE PARAMETERS PASSED IN!  
SET @bDate = @bDateStr
SET @eDate = @eDateStr
SET @district = @districtStr
.....

--PRESTO! The optimizer could once again use indexes as it should.

話の教訓は、オプティマイザは宣言された日時を使用してそのことを行うことができたということです。

于 2012-10-03T19:23:26.197 に答える
1

私は同じ問題を抱えています..netから実行された手順は時間がかかりすぎます(そして多くの行を返しません)。「execute stored_procedure @parameter1 = value1」という文字列をSQLに送信し、これをコピーしてSQL Management Studioで実行しましたが、すべて正常に実行されました。このケースの厄介な点は、クエリでパラメーター値に LETTER を追加または削除して原因を突き止めたことです。私はとても混乱しています。

情報として、ページングのために全文インデックスと一時テーブルを使用していますが、前述のように、SAME QUERY (そして確かに) は SQL Management Studio で完全に実行されます。

于 2009-12-13T00:56:21.933 に答える
0

Are dealerId or Lastname nvarchar (differently typed than the varchar parameters)?

This can cause conversion of entire indexes. If you find this to be the case, leave a comment and I will explain in more detail.

于 2009-10-02T13:45:24.430 に答える