【发布时间】:2012-05-17 02:54:52
【问题描述】:
我的问题是关于 Linq to SQL 性能,我有一个 SQL 字符串并将其转换为 Linq to sql:
SQL 查询:
SELECT CONVERT(VARCHAR(10), ClockIn, 103) AS ClockDate, MIN(ClockIn) AS ClockIn, MAX(ClockOut) AS ClockOut, SUM(DATEDIFF(MINUTE, ClockIn, ClockOut)) AS [TotalTime]
FROM TimeLog
WHERE (EmployeeId = 10)
GROUP BY CONVERT(VARCHAR(10), ClockIn, 103)
ORDER BY ClockIn DESC
LINQ 查询:
From u In objDC.TimeLogs
Where u.EmployeeId = 10
Group By Key = New With {u.ClockIn.Year, u.ClockIn.Month, u.ClockIn.Day} Into G = Group
Order By G.First.ClockIn Descending
Select New With {.ClockDate = Key.Day & "/" & Key.Month & "/" & Key.Year,
.ClockIn = G.Min(Function(p) p.ClockIn),
.ClockOut = G.Max(Function(p) p.ClockOut),
.TotalTime = G.Sum(Function(p) SqlMethods.DateDiffMinute(p.ClockIn, p.ClockOut))}
从 SQL 分析器中的 LINQ 生成的查询字符串是:
SELECT [t4].[value] AS [ClockDate], [t4].[value2] AS [ClockIn2], [t4].[value22] AS [ClockOut], [t4].[value3] AS [TotalTime]
FROM (
SELECT ((((CONVERT(NVarChar,[t3].[value32])) + '/') + (CONVERT(NVarChar,[t3].[value222]))) + '/') + (CONVERT(NVarChar,[t3].[value22])) AS [value], [t3].[value] AS [value2], [t3].[value2] AS [value22], [t3].[value3], [t3].[value22] AS [value222], [t3].[value222] AS [value2222], [t3].[value32]
FROM (
SELECT MIN([t2].[ClockIn]) AS [value], MAX([t2].[ClockOut]) AS [value2], SUM([t2].[value]) AS [value3], [t2].[value2] AS [value22], [t2].[value22] AS [value222], [t2].[value3] AS [value32]
FROM (
SELECT DATEDIFF(Minute, [t1].[ClockIn], [t1].[ClockOut]) AS [value], [t1].[EmployeeId], [t1].[value] AS [value2], [t1].[value2] AS [value22], [t1].[value3], [t1].[ClockIn], [t1].[ClockOut]
FROM (
SELECT DATEPART(Year, [t0].[ClockIn]) AS [value], DATEPART(Month, [t0].[ClockIn]) AS [value2], DATEPART(Day, [t0].[ClockIn]) AS [value3], [t0].[ClockIn], [t0].[ClockOut], [t0].[EmployeeId]
FROM [dbo].[TimeLog] AS [t0]
) AS [t1]
) AS [t2]
WHERE [t2].[EmployeeId] = 10
GROUP BY [t2].[value2], [t2].[value22], [t2].[value3]
) AS [t3]
) AS [t4]
ORDER BY (
SELECT [t6].[ClockIn]
FROM (
SELECT TOP (1) [t5].[ClockIn]
FROM [dbo].[TimeLog] AS [t5]
WHERE ((([t4].[value222] IS NULL) AND (DATEPART(Year, [t5].[ClockIn]) IS NULL)) OR (([t4].[value222] IS NOT NULL) AND (DATEPART(Year, [t5].[ClockIn]) IS NOT NULL) AND ((([t4].[value222] IS NULL) AND (DATEPART(Year, [t5].[ClockIn]) IS NULL)) OR (([t4].[value222] IS NOT NULL) AND (DATEPART(Year, [t5].[ClockIn]) IS NOT NULL) AND ([t4].[value222] = DATEPART(Year, [t5].[ClockIn])))))) AND ((([t4].[value2222] IS NULL) AND (DATEPART(Month, [t5].[ClockIn]) IS NULL)) OR (([t4].[value2222] IS NOT NULL) AND (DATEPART(Month, [t5].[ClockIn]) IS NOT NULL) AND ((([t4].[value2222] IS NULL) AND (DATEPART(Month, [t5].[ClockIn]) IS NULL)) OR (([t4].[value2222] IS NOT NULL) AND (DATEPART(Month, [t5].[ClockIn]) IS NOT NULL) AND ([t4].[value2222] = DATEPART(Month, [t5].[ClockIn])))))) AND ((([t4].[value32] IS NULL) AND (DATEPART(Day, [t5].[ClockIn]) IS NULL)) OR (([t4].[value32] IS NOT NULL) AND (DATEPART(Day, [t5].[ClockIn]) IS NOT NULL) AND ((([t4].[value32] IS NULL) AND (DATEPART(Day, [t5].[ClockIn]) IS NULL)) OR (([t4].
[value32] IS NOT NULL) AND (DATEPART(Day, [t5].[ClockIn]) IS NOT NULL) AND ([t4].[value32] = DATEPART(Day, [t5].[ClockIn])))))) AND ([t5].[EmployeeId] = 10)
) AS [t6]
) DESC
LINQ to SQL 太慢,生成查询的执行计划与 SQL 查询相比,人工编写的 SQL 查询为 7%,而 Linq 生成的查询为 97%。
我的 Linq to SQL 查询出了什么问题?还是 Linq 的性能和限制?
【问题讨论】:
-
欢迎来到泄漏抽象的世界。
-
编译查询可用,编译查询可以。
-
性能差异如此之大,您是否考虑过使用存储过程进行查询?如何:使用存储过程返回行集 (LINQ to SQL):msdn.microsoft.com/en-us/library/bb386975.aspx
-
谢谢@BeratBilgin,在这种情况下编译查询不能,因为我比较的是生成的查询和书面查询,而不是linq查询和sql查询,编译查询不会影响生成的查询。
-
谢谢@AndrewMorton,我可以直接使用来自datacontext的书面查询,不需要存储过程,但我的问题是关于Linq如何有用并且可以替代常规查询。似乎没有,您必须监视生成的查询并在某个时候将 Linq 替换为 String 查询。
标签: sql-server performance linq tsql linq-to-sql