Entity Frameworkのクエリを最適化する方法

entity-framework mysql performance

質問

私はLinq-to-Entitiesを使って947行しか返さないが実行に18秒かかるクエリを実行しています。基礎となるSQLを取り出すために "ToTraceString"を実行し、データベース上で同じことを直接実行し、同じタイミングを取得しました。

ほとんど影響はありませんが、チューニングアドバイザを使用して2つのインデックスを作成しました。

クエリ実行プランを見ると、95%の時間がかかるネストされたループがいくつかありますが、これらは既にインデックスに対して機能していますか?

EFクエリに最適化を強制する方法について誰かが何かアイデアを持っていますか?

編集:追加情報の提供

3つのテーブルの基本的なER図は次のとおりです。

People >----People_Event_Link ----< Events
P_ID        P_ID                    E_ID
            E_ID

私が実行しているlinqは、(P_IDを使用して)特定のPersonのためにすべてのイベントを取り戻すように設計されています。

        var query = from ev in genesisContext.Events
                    join pe in genesisContext.People_Event_Link
                    on ev equals pe.Event
                    where pe.P_ID == key
                    select ev;
        return query;

これが生成されたSQLです(深呼吸!):

SELECT 
1 AS [C1], 
[Extent1].[E_ID] AS [E_ID], 
[Extent1].[E_START_DATE] AS [E_START_DATE], 
[Extent1].[E_END_DATE] AS [E_END_DATE], 
[Extent1].[E_COMMENTS] AS [E_COMMENTS], 
[Extent1].[E_DATE_ADDED] AS [E_DATE_ADDED], 
[Extent1].[E_RECORDED_BY] AS [E_RECORDED_BY], 
[Extent1].[E_DATE_UPDATED] AS [E_DATE_UPDATED], 
[Extent1].[E_UPDATED_BY] AS [E_UPDATED_BY], 
[Extent1].[ET_ID] AS [ET_ID], 
[Extent1].[L_ID] AS [L_ID]
FROM  [dbo].[Events] AS [Extent1]
INNER JOIN [dbo].[People_Event_Link] AS [Extent2] ON  EXISTS (SELECT 
    1 AS [C1]
    FROM    ( SELECT 1 AS X ) AS [SingleRowTable1]
    LEFT OUTER JOIN  (SELECT 
        [Extent3].[E_ID] AS [E_ID]
        FROM [dbo].[Events] AS [Extent3]
        WHERE [Extent2].[E_ID] = [Extent3].[E_ID] ) AS [Project1] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent4].[E_ID] AS [E_ID]
        FROM [dbo].[Events] AS [Extent4]
        WHERE [Extent2].[E_ID] = [Extent4].[E_ID] ) AS [Project2] ON 1 = 1
    WHERE ([Extent1].[E_ID] = [Project1].[E_ID]) OR (([Extent1].[E_ID] IS NULL) AND ([Project2].[E_ID] IS NULL))
)
WHERE [Extent2].[P_ID] = 291

受け入れられた回答

はい。 LINQクエリを書き換えます。ほとんどのLINQ to Entitiesクエリはさまざまな方法で記述でき、SQLへの変換方法も異なります。 LINQもSQLもクエリプランも表示されていないので、私が言えるのはそれだけです。

ただし、SQLを直接実行してみるのは賢い方法です。クエリのコンパイルにも時間がかかることがありますが、SQLが測定された時間のすべてを占めていると判断することでこれを除外しました。

試してください:

    var query = from pe in genesisContext.People_Event_Link
                where pe.P_ID == key
                from ev in pe.Event // presuming one to many
                select ev;

またはpe.Eventが1対1の場合

    var query = from pe in genesisContext.People_Event_Link
                where pe.P_ID == key
                select pe.Event;

    return query;

人気のある回答

@Craig SelectManyの呼び出しに型推論が失敗したというエラーメッセージが表示されたため、クエリを機能させることができませんでした。

しかし、私はあなたのアドバイスを受けて、結合の使用からANSIタイプのクエリの前の「古いスタイル」に行きました。

        var query = from pe in genesisContext.People_Event_Link
                    from ev in genesisContext.Events
                    where pe.P_ID == key && pe.Event == ev
                    select ev;

これはかなりまともなSQLを生成します。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ