繁体   English   中英

LINQ查询性能低下

[英]Slow performance in LINQ query

我有这个来自在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查询?

尝试这样的东西,在分组之前将它带入内存:

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()
});

我真的怀疑你真的想在你的代码中的任何一点使用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(),
            };

快速浏览一下,我会调查你的部分grp.FirstOrDefault - 这真的是你想要做的吗?

在这种情况下,我肯定会选择参数化的存储过程。 您还应该考虑在所需的表上创建覆盖索引。 这些步骤通常会以非常显着的数量提升性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM