2016-10-11 5 views
2

したがって、Entity Framework 6のMySQLプラグインのパフォーマンスについて不平を言っている記事があります。しかし、これらのほとんどは、悪いSQLを生成しているようです。私はこの問題で苦しんでいるが、それはプラグイン自体に起因するパフォーマンスの遅れによるものと思われる。Entity Framework 6 MySQLとパフォーマンスの差異対MySQLエンジン

List<Address> matches = _rep.GetAddresses(s => s.AddressKey == cleanAddress).ToList(); 

をし、リポジトリ(_rep)に私はこれを持っている:

はここにLINQで私のクエリの

public IQueryable<Address> GetAddresses(Expression<Func<Address, bool>> query) 
{ 
    //var foo = Addresses.AsNoTracking().Where(query); 
    //var bar = foo.ToString(); 

    return Addresses.AsNoTracking().Where(query); 
} 

だから私はすでに試してみて、パフォーマンスを向上させるためにAsNoTrackingを使用しています。

SELECT 
`Extent1`.`AddressId`, 
`Extent1`.`AddressKey`, 
`Extent1`.`NameKey`, 
`Extent1`.`Title`, 
`Extent1`.`Forename`, 
`Extent1`.`Surname`, 
FROM `Addresses` AS `Extent1` 
WHERE (`Extent1`.`AddressKey` = @p__linq__0) 
OR ((`Extent1`.`AddressKey` IS NULL) AND (@p__linq__0 IS NULL)) 

十分なシンプル:コメントアウト行は、私があることが判明し、生成されていたSQLを、見ることができますがあります。 AddressKeyがインデックスを持つvarchar(255)列であることに注意してください。

ここには、事があります。私がそのクエリをMySQLワークベンチにスティックして実行した場合(実行時に登録されていない場合は、@p__linq__0の値が変わります)この時間は0.000秒と表示されます。

しかし、私のクエリの周りにストップウォッチを置き、Linqを実行するのにかかる時間を記録すると、約0.004秒で終了します。あなたが考える大きな違いはありませんが、これは何百万回もこのコードを実行するスピードクリティカルなアプリケーションの一部です。それはすぐに追加されます。

upsertコードの後のブロックで同じ問題が発生します。ワークベンチでネイティブに実行し、それはミリ秒未満です。再度、EFを介して、3〜4ミリ秒かかる。

これはEF MySQLプラグインの弱いデザインになっていると思いますか?もしそうなら、私はストアドプロシージャを介して実行するか、ExecuteSqlCommand()で直接SQLを実行しようとすると、同じ問題に遭遇するだろうと推測できますか?

このパフォーマンスの遅れを解消するために他に何かできますか?

+0

あなたは多くのコールを用いて測定した平均時間を話している、または(追加のオーバーヘッドを持っている、おそらく最初の)1つだけの呼び出し? –

+0

@IvanStoev EFログされた時間は、1kコールの平均です。 SQLの比較はいくつかの単一コールです。私は、EFが実際の操作でやっていたことを模倣しようと試みるたびに、探していたキーを変更しました。 –

+1

これは単なる推測ですが、実際にはEFクエリーの実行/マテリアライゼーションプロセスのオーバーヘッド、つまりMySQLプラグインとは無関係かもしれません。 [SqlQuery](https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Data.Entity.DbSet%601.SqlQuery); k(TargetFrameworkMoniker問題がEFやMySQLのプラグインにあるかどうかを判断するために単純な 'DbReader'と言っていますが、正直なところ私はあなたの要件/期待値を考えています。あまりにも高いです。 –

答えて

2

生成されたクエリとLINQ式の実行には大きな違いがあります。

は、Entity Frameworkの

は時々クエリ自体を実行するよりも時間がかかることがDbExpression

この部分にLINQの式を変換しないものを見てみましょう。いくつかのケースでは、複数のインクルードで、数百ミリ秒ほどのパフォーマンスが悪いと感じました。

は、クエリを生成するか、それが最初にSQLクエリを生成するためにいくつかの時間がかかることが

キャッシュからそれを取るが、サブシーケンス呼び出しがキャッシュから生成されたクエリがかかります。

キャッシュは、以前に生成されたDbExpressionを使用してキャッシュキーを作成します。

オブジェクトの実体を作成するには、マテリア

時間をクエリを実行するクエリ

サーバーレイテンシ+時間を実行します。 AsNoTrackingを使用して追跡する必要があるため、通常は非常に高速です。


私が間違っているかもしれないが、私の推測では、LINQの式がDbExpressionに変換されたときに、あなたの時間のほとんどが取られています。

ToTraceStringメソッドでクエリを実行せずにクエリを生成する時間を確認することで、簡単に検証できます。 TraceStringに直接使用する場合は、MySQL Interceptorの処理時間は考慮されませんが、少なくとも時間については大まかに考えてください。ここで

(私はそれをテストしていない)拡張メソッドをToTraceStringの例である:Obtain ToTraceString

関連する問題