1. ホーム
  2. performance

[解決済み] Entity Frameworkのクエリは遅いが、SqlQueryの同じSQLは速い。

2022-11-07 03:08:51

質問

.NET フレームワーク バージョン 4 で Entity Framework Code-First を使用した非常に単純なクエリに関連して、いくつかの本当に奇妙な現象が発生しています。LINQ2Entities クエリは次のようなものです。

 context.MyTables.Where(m => m.SomeStringProp == stringVar);

これは実行に3000ミリ秒以上かかります。生成されたSQLは非常にシンプルに見えます。

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = '1234567890'

このクエリは、Management Studio で実行すると、ほとんど瞬時に実行されます。SqlQuery 関数を使用するように C# コードを変更すると、5 ~ 10 ミリ秒で実行されます。

 context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);

つまり、全く同じSQLで、結果のエンティティはどちらも変更追跡されていますが、両者の間に野生の完全な違いがあります。どうしたのでしょうか?

どのように解決するのですか?

発見しました。SQLのデータ型の問題であることがわかりました。その SomeStringProp カラムはvarcharでしたが、EFは.NET文字列型がnvarcharであると仮定しています。その結果、DBが比較を行うためのクエリ中の変換処理に時間がかかっているのです。私はEF Profがここで私を少し迷わせたと思います、実行されるクエリのより正確な表現は次のようになります。

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = N'1234567890'

従って、結果として得られる修正は、コード・ファースト・モデルに正しいSQLデータ型を示すアノテーションを付けることです。

public class MyTable
{
    ...

    [Column(TypeName="varchar")]
    public string SomeStringProp { get; set; }

    ...
}