2011-10-24 10 views
5

de acuerdo a todas las muestras, la conversión de SQL para LINQ por haber cláusula como en este ejemplo:LINQ A GRUPO SQL por tener generada sólo como subconsulta

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

es: (vb.net)

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

pero la declaración de LINQ anterior se traduce en el siguiente 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 

nunca en condiciones de generar HAVING cláusula de forma LINQ. Digamos que HAVING y subconsulta group by WHERE son equivalentes en los resultados, pero ¿hay alguna diferencia en el rendimiento? ¿Qué hay de mantener mis consultas SQL originales al menos SIMILARES a las que LINQ genera subyacentes?

Respuesta

4

Puede demostrar si las dos consultas en cuestión se ejecutan de la misma manera por SQL Server visualizando los Planes de ejecución. Tome el siguiente código de prueba (utilicé 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 

La ejecución de estas consultas desde el Analizador de consultas SQL con "Incluir plan de ejecución real" seleccionado en el menú "Consulta" producirá el siguiente resultado:

execution plans

En este caso, dado que los planes de consulta generados son exactamente iguales, sin duda parece que no debe haber diferencia de rendimiento entre su SQL y el SQL generado a partir de su instrucción LINQ.

Como nota al margen, desafortunadamente, no pude encontrar ninguna documentación sobre por qué LinqToSql no utiliza HAVING, o si usar HAVING vs. usar una sub selección produce una ganancia de rendimiento de una forma u otra. Si tuviera que adivinar, diría que el optimizador de consultas en SQL Server internamente convierte estas declaraciones en la misma consulta antes de que se ejecuten, por lo que los planes de ejecución son idénticos para ambas sentencias. Independientemente de que mi declaración anterior sea cierta, diría que si alguna vez tiene dudas, simplemente consulte los Planes de ejecución para su versión de SQL en comparación con la versión de LinqToSql. Si son iguales, entonces no tiene nada de qué preocuparse en cuanto a rendimiento. Si su versión de SQL es mucho más eficiente, entonces siempre puede escribir un procedimiento almacenado y simplemente llamar al procedimiento almacenado utilizando LinqToSql.