LINQ TO SQL GROUP BY сгенерирован только как подзапрос - PullRequest
5 голосов
/ 24 октября 2011

согласно всем примерам, преобразование SQL в предложение LINQ for HAVING, как в этом примере:

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

Мне никогда не удавалось создать предложение HAVING из LINQ. Допустим, HAVING и группа подзапросов с WHERE эквивалентны в результатах, но есть ли разница в производительности? как насчет того, чтобы мои исходные SQL-запросы были по крайней мере аналогичны тем, которые генерирует LINQ?

1 Ответ

4 голосов
/ 23 ноября 2011

Вы можете продемонстрировать, выполняются ли два рассматриваемых запроса одинаково в 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 Query Analyzer с выбранным в меню «Запрос» «Включить фактический план выполнения» даст следующий вывод:

execution plans

В этом случае, поскольку сгенерированные планы запросов точно такие же, очевидно, что не должно быть никакой разницы в производительности между вашим SQL и SQL, сгенерированным из вашего оператора LINQ.

В качестве дополнительного примечания, к сожалению, я не смог найти никакой документации о том, почему LinqToSql не использует HAVING, или если использование HAVING по сравнению с использованием дополнительного выбора приводит к увеличению производительности тем или иным способом,Если бы мне пришлось угадывать, я бы сказал, что оптимизатор запросов в SQL Server внутренне превращает эти операторы в один и тот же запрос до их выполнения, поэтому планы выполнения идентичны для обоих операторов.Является ли мое предыдущее утверждение верным, я бы сказал, что если у вас есть какие-либо сомнения, просто проверьте планы выполнения для вашей версии SQL по сравнению с версией LinqToSql.Если они одинаковые, то вам не о чем беспокоиться по поводу производительности.Если ваша версия SQL намного эффективнее, вы всегда можете написать хранимую процедуру и просто вызвать хранимую процедуру с помощью LinqToSql.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...