5

すべてのサンプルによると、次の例のように HAVING 句の LINQ への SQL 変換:

SELECT NAME
FROM TABLES
GROUP BY NAME
HAVING COUNT(*) > 1

は: (vb.net)

from t in tables 
group t by t.NAME into g = Group 
where g.count > 1 
select g

しかし、上記の LINQ ステートメントは次の SQL に変換されます。


SELECT [t1].[NAME] AS [Key]
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME]
    FROM [tables] AS [t0]
    WHERE [t0].[NAME] <> @p0
    GROUP BY [t0].[NAME]
    ) AS [t1]
WHERE [t1].[value] > @p1

LINQ から HAVING 句を生成することに成功したことはありません。HAVING と subquery group by with WHERE の結果は同じですが、パフォーマンスに違いはありますか? 元の SQL クエリを、少なくとも LINQ が生成する基盤と同じ程度に保つのはどうですか?

4

1 に答える 1

4

実行プランを表示することで、問題の 2 つのクエリが SQL Server によって同じ方法で実行されるかどうかを示すことができます。次のテスト コードを使用します (私は SQL Server 2008 を使用しました)。

CREATE TABLE #TABLES ([ID] INT IDENTITY, [Name] VARCHAR(30))
INSERT INTO #TABLES VALUES('A')
INSERT INTO #TABLES VALUES('A')
INSERT INTO #TABLES VALUES('B')
INSERT INTO #TABLES VALUES('C')
INSERT INTO #TABLES VALUES('D')

SELECT NAME
FROM #TABLES
WHERE [Name] <> 'D'
GROUP BY NAME
HAVING COUNT(*) > 1

SELECT [t1].[NAME]
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME]
    FROM [#TABLES] AS [t0]
    WHERE [t0].[NAME] <> 'D'
    GROUP BY [t0].[NAME]
    ) AS [t1]
WHERE [t1].[value] > 1

DROP TABLE #TABLES

[クエリ] メニューで [実際の実行計画を含める] を選択して SQL クエリ アナライザーからこれらのクエリを実行すると、次の出力が得られます。

実行計画

この場合、生成されたクエリ プランはまったく同じであるため、実際の SQL と LINQ ステートメントから生成された SQL の間にパフォーマンスの違いはないように見えます。

残念ながら、残念ながら、LinqToSql が HAVING を使用しない理由、または HAVING を使用した場合とサブセレクトを使用した場合にいずれかの方法でパフォーマンスが向上するかどうかに関するドキュメントは見つかりませんでした。推測する必要がある場合、SQL Server のクエリ オプティマイザーは、これらのステートメントを実行前に内部的に同じクエリに変換します。これが、両方のステートメントの実行プランが同一である理由です。私の前の声明が真実であるかどうかにかかわらず、疑問がある場合は、SQL バージョンと LinqToSql バージョンの実行計画を確認してください。それらが同じであれば、パフォーマンスに関して心配する必要はありません。SQL バージョンがはるかに効率的である場合は、いつでもストアド プロシージャを作成し、LinqToSql を使用してストアド プロシージャを呼び出すことができます。

于 2011-11-23T15:52:24.777 に答える