3

私はこのコードを持っています:

DbSet<TableName> table = ...// stored reference

var items = from n in table where
            n.Name.ToUpper().Contains(searchString.ToUpper().Trim())
            select n;
WriteToLog( items.ToString() );

最後の行は、生成されたSQLを出力します。これが私が得るものです:

SELECT 
    [Extent1].[Name] AS [Name],
    // all the other columns follow
FROM (SELECT 
  [TableName].[Name] AS [Name],
  // all the other columns follow
FROM [dbo].[TableName] AS [TableName]) AS [Extent1]
WHERE ( CAST(CHARINDEX(LTRIM(RTRIM(UPPER(@p__linq__0))), UPPER([Extent1].[Name])) AS int)) > 0

ほら、それは完全に冗長ですが、-から-があります-SELECTそれで十分でしょう。EFを使用するコードは、30分より長く実行され、テーブルはかなり小さいですが、そのクエリでタイムアウトになります。SELECTSELECT

この過剰に設計されたSQLクエリが生成されるのはなぜですか。また、EFがより適切なクエリを生成するようにするにはどうすればよいですか。

4

2 に答える 2

8

式ツリーを変換することにより、結果のSQLを生成します。その変換を行った方法の副作用として、(たとえば、サブクエリを使用して)過剰に設計されているように見えます。変換の詳細は独自のものであり、複雑であり、結果は人間が読める形式ではありません。

問題は完全には明確ではありません-そしてあなたは私が問題ではないと信じている問題を解決しようとしています。生成されたクエリと独自のクエリを比較してみてください-クエリオプティマイザーは、このような簡単な最適化の短い作業を行うと思います。

私の推測(そして、LINQ to Entities MS開発者が来ない限り、これはおそらくここで得られる最良の答えです)は、彼らがまさにそれを行っているということです:最も効果的なクエリを生成しますが、頭を痛めつけるほど難しい仕事を残しますクエリを、SQLServerのクエリオプティマイザーにすでに数百または数千の工数を費やしているビットに最適化します。

于 2012-10-09T12:04:32.480 に答える
3

それは余分なことをしますSelectが、Selectsには関連する費用はありません。推定されたクエリプランを確認でき0%、その中にコストが表示されます。EFはOracle、SQLサーバーなどのさまざまなRDBMSシステムと互換性があり、最大限の互換性を確保するために、これを実行している可能性があります。

ただし、EntityFrameworkがUGLYsqlを生成することに同意します。あなたが与えた例は非常に単純なLinqクエリであり、クエリが複雑になり始めると、その醜さがさらにわかります。

1)これはあなたの答えに答えるかどうかはわかりませんが、PetaPocoのようなマイクロORMを使用すると思います。

https://github.com/toptensoftware/PetaPoco

またはDapper.Net

https://github.com/SamSaffron/dapper-dot-net

私は自分のプロジェクトの1つでそれを使用しており、プレーンなAdo.Netで得られる生の速度に完全に満足しています。

2)私の2番目の提案は、少なくとも Selectステートメントには常にストアドプロシージャを使用することです。挿入、更新、削除の場合は、おそらくEFを使用し、変更追跡メカニズムを利用する必要があります。これにより、面倒なクエリを作成する時間を節約できますが、少なくともSelectステートメントでは、プレーンSQLを使用する必要があります。これにより、SQLの自由度が高まります。生成されます。

于 2012-10-09T12:52:25.547 に答える