2

このLINQ式:

var result = entities.Cases
            .Where(c => c.House.Address.Contains("otte"))
            .ToList();

サーバーでこのSQLを実行します。

SELECT 
...
--rows
...
FROM  [dbo].[Case] AS [Extent1]
INNER JOIN [dbo].[House] AS [Extent2] ON [Extent1].[HouseID_FK] = [Extent2].[HouseID]
WHERE [Extent2].[Address] LIKE '%otte%'

これは完了するのに約100ミリ秒かかります。

このLINQ式:

var value = "otte";
var result = entities.Cases
            .Where(c => c.House.Address.Contains(value))
            .ToList();

サーバーでこのSQLを実行します。

exec sp_executesql N'SELECT 
...
--rows
...
FROM  [dbo].[Case] AS [Extent1]
INNER JOIN [dbo].[House] AS [Extent2] ON [Extent1].[HouseID_FK] = [Extent2].[HouseID]
WHERE [Extent2].[Address] LIKE @p__linq__0 ESCAPE N''~''',N'@p__linq__0     nvarchar(4000)',@p__linq__0=N'%otte%'

これは、完了するまでに約1400ミリ秒かかります。

「value」を定数として宣言すると、「高速」SQLも生成できますが、実行時に「value」の値を変更できるようにしたいと思います。EntityFrameworkに「execsp_executesql」を生成しないように強制する方法はありますか?これは明らかにはるかに遅いのでスタイルsqlですか?

4

1 に答える 1

1

hereに続いて、SQL Server (LINQ/EF) があなたの裏をかこうとしており、別のパラメーターを使用してそのクエリを再利用しようとしていることがわかり、sp_executesql を利用することが現在推奨されている方法であることをお勧めします。そのクエリを一貫して実行すること (これは、SQL Server がクエリを効率的にキャッシュできるようにするためです)。この 1 つのクエリを失う可能性がありますが、再利用することでペナルティを取り戻すことができますか?

データベースを変更して、単純なパラメーター化または強制的なパラメーター化 (「強制」が必要) を要求することを検討できますが、これにより、他のクエリではパフォーマンスが大幅に低下する可能性がありますが、YMMV.

SQL Server 自体で文字列を比較することは避けることをお勧めします...最近は RAM が豊富にあり、対応する 2 つのデータセットを持ち上げて C# で文字列値を比較する方が高速な場合があることがわかりました (再び、YMMV)

それができない場合は、要件に応じて、 SOUNDEXまたはDIFFERENCELIKEまたはCHARINDEXを比較して、パフォーマンスが向上するかどうかを確認してください。

幸運を。

于 2012-09-14T09:34:49.233 に答える