6

まず、ARITHABORT OFFをSSMSで試したところ、まだ1秒未満でした。Ef LinqのクエリはSSMSで1秒未満です。

私はEntityFrameWorkを使用

:6.1.3とAzureのSQLのS1層(IがTier 3にしようとすると、何かが変わるかどうかを知るようになる。)

私は、LINQからSQLを生成取得するEFプロファイラを使用しています。私は共有しているすべてのlinqを照会しました。それらはすべてSSMS上で1秒未満です。

私はAuditLogテーブルに300万の記録を持っています。 ID 3の顧客は170Kのレコードを持ち、ID 35の顧客は125のレコードを持っています。コードを最小限に抑えます。

監査ログモデル:

public class AuditLog 
    { 
    public long? CustomerId { get; set; } 

    [ForeignKey("CustomerId")] 
    public virtual CustomerSummary Customer { get; set; } 

    [Required] 
    [Index] 
    public DateTime CreatedDate { get; set; } 
    } 

まずクエリ:

if (customer != null) 
    { 
     var customerId = customer.Id; 
     var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList(); 
    } 

私は170Kの行を持っている顧客としようとすると、それが例外を時間を与えます。 125件のレコードを持っている顧客と一緒に試してみるといいですね。

第2クエリ:これは最初のものと同じですが、私は顧客を含んでいます。

if (customer != null) 
    { 
     var customerId = customer.Id; 
     var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList(); 
    } 

結果は最初のクエリと逆です。 170k行の顧客と一緒に試してみるといいですね。 125レコードある顧客と一緒に試してみると、タイムアウト例外が発生します。

第3のクエリ:これは最初のクエリと同じですが、私はとcustomerIdの一致します。

if (customer != null) 
    { 
     long? customerId = customer.Id; 
     var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList(); 
    } 

結果は最初のクエリとは逆です。 170k行の顧客と一緒に試してみるといいですね。 125レコードある顧客と一緒に試してみると、タイムアウト例外が発生します。

第4のクエリ:第2のクエリと同じですが、私はとcustomerIdの一致します。

if (customer != null) 
    { 
     long? customerId = customer.Id; 
     var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList(); 
    } 

結果は2番目のクエリと逆です。 170k行の顧客と一緒に試してみると、タイムアウト例外が発生します。 125件のレコードを持っている顧客と一緒に試してみるといいですね。

私は本当に混乱しています。なぜ内的に参加するか、または一致するパラメータをlong?に変更すると結果が変わるのですか?そして、なぜこのすべてのクエリがSSMSで1秒以下で実行され、ef linqでエラーが発生するのですか?

エラー:

{System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)

更新(19/04/2016):コメントの

Ivan Stoev後の提案。

Have you tried (just for the sake of test) using hardcoded 3 and 35 instead of customerId variable?

SSMSのようにエラーは発生せず、クエリも最速です。

更新(20/04/2016):実際の問題はパラメータスニッフィングです。パラメータをnullableに含めたり変更したりすると、実際に別のクエリと別のクエリプランが作成されました。私は125のレコードを持つ顧客と、これらの4つのクエリの170kのレコードを持つ顧客とのいくつかのプランを作成しました。だから私は別の結果を得ました。

+0

どのようにして結果を比較しているようなあなたのスニペットを更新しますか?あなたはEFによって生成されたSQLと比較しているのですか、または自分で書いていますか? –

+0

EFによって生成されたSQL。 –

+0

それは面白いです。使用しているEFのバージョンも指定すると便利です。 –

答えて

4

あなたが経験していることは、Parameter Sniffing Problemという結果です。これまでの単純な一般的な解決策はわからないので、普通は式の中に定数値を手作業でバインドしてSQLクエリパラメータのいくつかを削除して回避策を提案します(EntityFramework LINQ query count fails but query returns result. How to optimize LINQ query?など)。あなたのシナリオでは

は、私は次のカスタム拡張メソッドを示唆している:

public static class QueryableExtensions 
{ 
    public static IQueryable<T> WhereEquals<T, TValue>(this IQueryable<T> source, Expression<Func<T, TValue>> selector, TValue value) 
    { 
     var predicate = Expression.Lambda<Func<T, bool>>(
      Expression.Equal(selector.Body, Expression.Constant(value)), 
      selector.Parameters); 
     return source.Where(predicate); 
    } 
} 

をしてから、この

if (customer != null) 
{ 
    var result= Dbset.WhereEquals(x => x.CustomerId.Value, customer.Id) 
     .OrderByDescending(x => x.CreatedDate) 
     .Skip(0).Take(25) 
     .Include(x => x.Customer) 
     .ToList(); 
} 
+0

こんにちはIvan、 'var ListItems =(from pl。_context.Order where!pl.SentDateUTC.HasValue select pl).ToList(); ' はこの場合、パラメータスニッフィングのケースですか?上記の単純なLinqは、クエリの実行中にタイムアウト例外で失敗したためです。 この問題を解決するお手伝いをしてもらえますか? –

+0

@yogendarjiこんにちは、あなたのケースは異なります。なぜなら、クエリはパラメータを使用しないからです。基本的に 'pl.SentDateUTC == null'を探しています。ほとんどの場合、フルテーブルスキャンを実行している可能性があります。しかし、それほど時間をかけてはいけません.DBテーブルにはいくつのレコードがありますか? –

+0

私は約150kのレコードをテーブルに持っています。クエリプランを使用すると、非クラスタインデックスを作成することができます。その列にインデックスを作成する必要がありますか? –

関連する問題