0

ちょっとしたパフォーマンスの問題に遭遇しました。次のデータベースモデルを取得しました。 モデル

Entity1 に外部キーを持たない Entity2 のすべてのエントリを選択したい、つまり、ナビゲーション プロパティを null にする必要があります。

次の LINQ クエリを思いつきましたが、context.Entity2Set.Where(x => x.Entity1 == null);動作しますが、遅いです。そのため、エントリを選択するためのより良い (より高速な) 方法 (インデックス作成以外) があるかどうか疑問に思っていました。

最終的には Entity4 からエントリを選択したいので、パフォーマンスが問題になります。

4

2 に答える 2

2

Entity2依存関係()ではなく、関係()のプリンシパルをクエリしていEntity1ます。これは、外部キーがテーブルEntity1にあり、生成されたSQLクエリがテーブルの列値のクエリではないことを意味しますEntity2。目的の結果を得るには、SQLクエリLEFT OUTER JOINが2つのテーブルを(によって)結合する必要があります。

1対多の関係の場合、クエリは「注文アイテムのないすべての注文を取得する」のようになります。Orderこれは、外部キーがテーブル内OrderItemにあり、クエリが2つのテーブルを結合する必要があるため、テーブルだけを検査することによっては達成できません。実際、この例では、テーブルの外部キー列にインデックスを付けることで、クエリのパフォーマンスを向上させることができますOrderItem

残念ながら、この例では、1対1の関係(1対多ではない)があるため、列にインデックスを付けてクエリを改善することはできません。EFの1対1の関係は常に共有主キーの関連付けであるため、テーブル内の外部キーが同時にEntity1その主キー になります。Id

これは、外部キー列がすでにインデックス付けされていることを意味します。つまり、テーブル内のクラスター化された主キーインデックスによってインデックス付けされていますEntity1

生成されるSQLクエリは次のようになります。

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[OtherColumn] AS [OtherColumn]
FROM   [dbo].[Entity2] AS [Extent1]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent3] ON [Extent2].[Id] = [Extent3].[Id]
WHERE [Extent3].[Id] IS NULL

ご覧のとおり、テーブルはインデックス付きのId列で結合されています。2番目の冗長なLEFT OUTER JOINものは、EF<5.0で有効だったEntityFrameworkのSQL生成の欠陥です。EF>=5.0で解決されるかどうかはわかりません。行が同じ列でテーブルとテーブルを結合しているため、クエリのパフォーマンスにとって本当に重要かどうかはわかりません。SQLクエリオプティマイザがそれを認識し、実行プランの行を​​無視することを期待します。

本質的に:LINQクエリは問題なく、列にインデックスを追加しなくてもパフォーマンスを向上させることはできません。

しかし、私が提案するのは、本当に遅いものを見つけることです。それは確かにSQLクエリですか、それともLINQクエリからSQLへの変換ですか、それとも返された結果セットのオブジェクトの具体化などですか?私が行う最初のステップは、生成されたSQLクエリをSQL Server Management Studioに貼り付けて、パフォーマンスがどのようになっているのかを確認することです。LINQクエリを変更しない場合でも、パフォーマンスを向上させる他の機会がある可能性があります。

于 2013-02-17T16:15:07.293 に答える
0

あなたは言った

インデックスなし

しかし、この問題ではそれは間違いです。インデックスは、ほぼ瞬時にすべての null 参照を見つけます。

于 2013-02-17T15:17:29.340 に答える