1

EntityFramework4.4で発生しているパフォーマンスの問題についてサポートが得られることを期待していました。EDMXファイルを使用していたアプリケーションを最初にコードに変換する作業を行っていますが、LINQクエリの「where」句に多数のオブジェクトを含むクエリを実行すると問題が発生します。

すべてがどのようにレイアウトされているかについての簡単な概要を次に示します(エンティティはEFを参照せず、コード内の一般的な「もの」に付けられた名前です)。

public class ExampleDbContext : DbContext
{
    public DbSet<EntityTag> EntityTags { get; set; }
    public DbSet<Entity> Entities { get; set; }

    public DbSet<Log> Logs { get; set; }

    protected override void OnModelCreating(DbmodelBuilder modelBuilder)
    {
        // Fluent mappings added to modelBuilder.Configurations.Add() in here
    }
}

public class EntityTag
{
    public int Id { get; set; }

    public virtual Entity Entity { get; set; }
    public int EntityId { get; set; }

    public virtual Log Deleted { get; set; }
    public int? DeletedId { get; set; }
}

public class Entity
{
    public int Id { get; set; }

    pulic byte[] CompositeId { get; set; }
}

// Used to log when an event happens
public class Log
{
    public int Id { get; set; }

    public string Username { get; set; }
    public DateTime Timestamp { get; set; }
}

問題を引き起こす私が実行しているクエリは次のとおりです。

// Creates an IEnumerable<byte[]> with the keys to find
var computedKeys = CreateCompositeIDs(entityKeys);

// Run the query and find any EntityTag that isn't deleted and is in
// the computedKeys list
var result = from et in Context.EntityTags
             where computedKeys.Contains(et.Entity.CompositeId) &&
                   et.Deleted == null
             select et;

var entityTags = result.ToList();

計算されたキーに含まれるIDが数個(たとえば15個)の場合、コードとクエリはすばやく実行されます。多数のIDがある場合(この時点では1600は正常であり、さらに高くなる可能性があります)、で列挙されたクエリを実行するのに数分かかります(500では、まだ1500で試していません)ToList()computedKeys.Contains()また、クエリから(et.Deletedを残して)を削除したところcomputedKeys、クエリがすぐに実行されてしまいました。

デバッグを通じて、キーのリストの作成は高速であると判断したので、それは問題ではありません。プロファイラーをMSSQLに接続して、生成されたクエリを確認すると、すべてのCompositeIdがに含まれているという点で正常に見えますWHERE CompositeId IN ( /* List of Ids, could be 1500 of them */)。クエリがプロファイラーに表示されると、1秒以内に実行されるため、そうではないと思います。データベースの最適化も。プロファイラーは、すぐに結果を返すときに、最後の1秒程度を除いて、実行中ずっと何も表示されずにそこに座っています。

dotTraceを接続したところ、System.Data.Query.PlanCompiler.JoinGraph.GenerateTransitiveEdge(JoinEdge, JoinEdge)(119,640 ms)以内に多くの時間が費やされSystem.Collections.Generic.List+Enumeratorているようで、それぞれの合計実行時間に基づいて、そのメソッド内で1.MoveNext`(54,270 ms)が2回呼び出されたと思います。

クエリの生成に時間がかかる理由がわからないようです。コンパイル後の2回目の実行も高速ではないように思われるため、キャッシュされているようには見えません。

助けてくれてありがとう!

4

1 に答える 1

0

私はそれを理解することができました。元のクエリにとらわれずに結果を再検討した後、クエリを次のように書き直しました。

var computedKeys = CreateCompositeIDs(entityKeys);

var entityTags = (from e in Context.Entities
                  where computedKeys.Contains(e.CompositeId)
                  from et in e.Tags
                  select et).Distinct();
entityTags = from et in entityTags
             where et.Deleted == null
             select et;

return entityTags;

エンティティに直接クエリを実行し、EntityTag(元の質問に含めるのを忘れていた...)との関係を利用して、既存のオブジェクトTagsのみをフィルタリングするEntityTagと、クエリが高速化され、すべてが1つで実行されるようになりました。 2番目。

于 2013-02-11T16:35:05.653 に答える