我有这个来自在Cold Fusion上运行的旧系统的t-sql查询。此查询返回记录的时间不到一秒。
select dateDiff(month, dateAdd(hour, 11, createdAt), {ts '2015-02-28 23:59:59'}) p, count(*) c
from account
where createdAt <= {ts '2015-02-28 23:59:59'}
and accountType = 'business'
and dateDiff(month, dateAdd(hour, 11, createdAt), {ts '2015-02-28 23:59:59'}) <12
group by dateDiff(month, dateAdd(hour, 11, createdAt), {ts '2015-02-28 23:59:59'})
order by dateDiff(month, dateAdd(hour, 11, createdAt), {ts '2015-02-28 23:59:59'})
我现在使用.NET和LINQ将其转换为新系统。 我设法写了这个LINQ查询,它给了我相同的结果。
from a in db.Accounts
where SqlFunctions.DateDiff("Month", SqlFunctions.DateAdd("Hour", 11, a.createdAt), "2015-02-28 23:59:59") < 12
&& a.accountType == "business"
group a by SqlFunctions.DateDiff("Month", a.createdAt, "2015-02-28 23:59:59") into grp
orderby SqlFunctions.DateDiff("Month", grp.FirstOrDefault().createdAt, "2015-02-28 23:59:59")
select new ProgressViewModel.Data
{
date = SqlFunctions.DateDiff("Month", grp.FirstOrDefault().createdAt, "2015-02-28 23:59:59"),
amount = grp.Count()
});
但是,此查询运行时间不少于5秒,而第一个查询(t-sql)则需要不到1秒。
通过使用Glimpse,我们可以看到LINQ查询生成的t-sql。它有多个子选择,比快速查询长5倍。
我如何改进LINQ查询?
答案 0 :(得分:2)
在分组之前尝试这样的事情将其带入内存:
from ca in (
from a in db.Accounts
where SqlFunctions.DateDiff("Month", SqlFunctions.DateAdd("Hour", 11, a.createdAt), "2015-02-28 23:59:59") < 12 && a.accountType == "business"
select a.createdAt).ToArray()
group a by new /* month diff */ into grp
orderby grp.Key
select new ProgressViewModel.Data
{
date = grp.key,
amount = grp.Count()
});
答案 1 :(得分:1)
我真的怀疑你确实想在代码中的任何一点使用FirstOrDefault()
。
BTW看起来您正在使用LinqToSQL作为您的Linq提供商。那东西是讨厌,低效和彻头彻尾的马车。如果可能的话,你应该切换到EntityFramework
考虑到......也许你应该试试这个......
var date = new Date(2015, 2, 28).AddDays(1);
var query = from account in context.Accounts
where account.CreatedAt < date
where account.accountType == "business"
group account by
SqlFunctions.DateDiff(
"Month",
SqlFunctions.DateAdd(
"Hour", 11, a.createdAt),
date)
into g
where g.Key < 12
order by g.Key ascending
select new
{
MonthsAgo = g.Key,
Count = g.Count(),
};
答案 2 :(得分:0)
快速浏览一下,我会调查您的部分grp.FirstOrDefault - 这真的是您想要做的吗?
答案 3 :(得分:-1)
在这种情况下,我肯定会选择参数化的存储过程。您还应该考虑在所需的表上创建覆盖索引。这些步骤通常会以非常显着的数量提升性能。