如何从Linq2Sql查询生成更好的SQL

时间:2010-07-15 21:31:51

标签: sql linq-to-sql optimization

我有以下查询:

var data = from d in dc.GAMEs 
    where (d.GAMEDATE + d.GAMETIME.Value.TimeOfDay) >= DateTime.Now select d; 

这会生成一些看起来很像的SQL,看起来像这样:

SELECT {...} WHERE DATEADD(ms, ((CONVERT(BigInt,((CONVERT(BigInt,DATEPART(HOUR, [t0].[GAMETIME]))) * 36000000000) + ((CONVERT(BigInt,DATEPART(MINUTE, [t0].[GAMETIME]))) * 600000000) + ((CONVERT(BigInt,DATEPART(SECOND, [t0].[GAMETIME]))) * 10000000) + ((CONVERT(BigInt,DATEPART(MILLISECOND, [t0].[GAMETIME]))) * 10000))) / 10000) % 86400000, CONVERT(DateTime,DATEADD(day, (CONVERT(BigInt,((CONVERT(BigInt,DATEPART(HOUR, [t0].[GAMETIME]))) * 36000000000) + ((CONVERT(BigInt,DATEPART(MINUTE, [t0].[GAMETIME]))) * 600000000) + ((CONVERT(BigInt,DATEPART(SECOND, [t0].[GAMETIME]))) * 10000000) + ((CONVERT(BigInt,DATEPART(MILLISECOND, [t0].[GAMETIME]))) * 10000))) / 864000000000, [t0].[GAMEDATE]))) >= @p0

这么多SQL的原因是什么?是否有更好的方法来处理它?<​​/ p>

编辑:

我无法控制架构。它就是这样,我必须处理它。

2 个答案:

答案 0 :(得分:2)

如果您可以更改架构,那么处理架构的最佳方法是使用单个datetime2列,而不是单独的datetime字段。您当前的查询将无法使用索引。

否则您可以尝试重写查询,如下所示:

DateTime now = DateTime.Now;
var data = from d in dc.GAMEs 
    where (d.GAMEDATE > now.Date) ||
          (d.GAMEDATE == now.Date && d.GAMETIME.Value.TimeOfDay >= now.TimeOfDay)
    select d; 

此查询生成的SQL可能稍微更具可读性,也可能更高效。另一方面,从程序员的角度来看,源代码的可读性比生成的SQL可读更重要。如果性能不是问题,您可能希望保留代码,只是接受生成的SQL很难看而不用担心。

答案 1 :(得分:0)

作为替代方案(因为最外层的OR是索引的祸根)

DateTime now = DateTime.Now;
DateTime today = now.Date;
TimeSpan timeOfDay = now.TimeOfDay;

var data =
  from d in dc.GAMEs  
  where d.GAMEDATE >= today
    && (d.GAMEDATE > today || d.GAMETIME.Value.TimeOfDay >= timeOfDay) 
  select d;