Linq日期性能死亡

3
我有一个将日期分解为整数存储的数据库。例如,日,月和年分别存储在不同的列中。
现有SQL查询使用的方法是:
DATEADD(dd, - 1, DATEADD(mm, Z.LastMonth, DATEADD(yy, Z.LastYear - 1900, 0))) AS last_date 我无法更改数据库以存储日期。
进一步查看dateadd()函数时,它是从一个整数(0)进行转换的。 Linq to SQL没有类似的功能,即Convert.ToDateTime(0)。这会导致InvalidCastException。
我已尝试将字符串连接起来创建日期,但速度非常慢。时间差约为10分钟。
还能做什么?我特别不想开始将SQL查询混入项目中。
谢谢。

你为什么不一开始就将这个信息存储为日期呢? - rossisdead
我不这么认为。但是我现在无法更改它。 - Mike
6个回答

3

你可以简单地写:

table.Select(z => new DateTime(z.LastYear, z.LastMonth, z.LastDay));

好的,我在Linqpad中进行了测试,似乎Linq to SQL确实会生成一些奇怪的字符转换查询。我并不完全相信这是性能问题的根源,但您可以像这样强制进行投影:

var dates = 
    (from z in table
     select new { Year = z.LastYear, Month = z.LastMonth, Day = z.LastDay })
    .AsEnumerable()
    .Select(d => new 
        {
            Date = new DateTime(d.Year, d.Month, d.Day),
            NextDate = new DateTime(d.Year, d.Month, 1).AddMonths(2).AddDays(-1)
        });

这也将为您获取下个月的最后一天。

如果您真的看到了如此巨大的性能差异,我猜测您正在寻找错误的地方,可能有其他原因导致。90%的与数据库相关的性能问题都是由于索引不良或不存在、查询无法进行优化等原因导致的。


嘿,那是个好主意...我为什么没想到呢!谢谢。 - Mike
那比字符串拼接快得多。我觉得它的速度比dateadd()函数慢。暂时就这样吧。再次感谢,伙计。 - Mike
@Mike:不要凭感觉,进行分析!我很难想象这样一个简单的投影比SQL中的一堆日期操作慢得多。 - Aaronaught
我之前在工作中留下了一个未注释的SQL查询语句,这就是我在调试窗口中看到的内容。进一步研究后发现,它渲染的SQL与字符串连接相同。因此,这没有任何区别。 - Mike
我需要获取下个月的最后一天,所以我这样做:new DateTime(z.LastYear, z.LastMonth, z.LastDay).AddMonths(1).AddDays(-1); 这会输出一些超级复杂的SQL,并且也需要一些时间。DATEADD(ms, (CONVERT(BigInt,@p17 * 86400000)) % 86400000, DATEADD(day, (CONVERT(BigInt,@p17 * 86400000)) / 86400000, DATEADD(MONTH, @p18, CONVERT(DATETIME, CONVERT(NCHAR(2), [Z].[LastMonth]) + ('/' + (CONVERT(NCHAR(2), @p19) + ('/' + CONVERT(NCHAR(4), [Z].[LastYear])))), 101)))) - Mike

3
您可以使用 LINQ to SQL 将其映射到自定义的 SQL 语句或存储过程,以获得相同的 SQL 性能。

1
我也会选择视图或存储过程。+1 - leppie

1

1
你能在数据库中添加一个视图吗?如果可以的话,你可以定义一个视图,它看起来就像你的表格,只是有一个真正的日期,因为它是由你把那些疯狂的列转换成日期的查询支持的。然后只需使用LINQ查询即可。我不记得SQL Server是否具有智能视图缓存,但如果有的话,它可能比直接使用SQL更有效率。

0
在性能方面,我假设这个日期是您的主要过滤条件(您希望被索引的条件)。
如果是这样的话:
  • 确保索引中的列顺序为年、月、日。
  • 不要将日期条件作为日期时间发送到数据库中,而是发送整数。如果在过滤之前将表列转换为日期,则索引无效。

0
请注意:比字符串拼接方法更快的方法是创建字符数组并自行设置字符数组的元素。如果您可以在编译时控制字符串的大小,这种方式最为实用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接