Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ查询中的低性能_C#_.net_Sql Server_Linq - Fatal编程技术网

C# LINQ查询中的低性能

C# LINQ查询中的低性能,c#,.net,sql-server,linq,C#,.net,Sql Server,Linq,我有一个t-sql查询,它来自一个运行在Cold Fusion上的旧系统。此查询返回记录的时间不到1秒 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' an

我有一个t-sql查询,它来自一个运行在Cold Fusion上的旧系统。此查询返回记录的时间不到1秒

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秒

通过使用scape,我们可以看到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()
});

快速查看一下,我将调查您的grp.FirstOrDefault部分-这真的是您想要做的吗?

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

我真的怀疑您是否真的想在代码中的任何时候使用FirstOrDefault

顺便说一句,看起来您正在使用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.firstOrDefuilt看起来很可疑-你不是说grp.Key吗?另外,为什么不添加传递的参数,而不是数据库中的值?这应该允许您在createdAt上使用索引(如果有)。您能让我们知道生成的LINQ查询是什么样子吗?我找不到条件createdAt dam…upvoted的等效项,而不进行真正的查找。刚意识到这是一个非常糟糕的查询,因为它是在memory@Aron-为什么在记忆中不好?通常情况下,它比不引入它要快。这真的取决于你正在尝试优化什么。因此,在这种情况下,你至少可以将帐户转换为开销较低的帐户。嗨,神秘性,我感谢你的回答,但是,我选择的是在选择之前不将数据加载到内存中的帐户。但我在过去也这样做过,因为首先将数据加载到内存中,然后进行操作比从数据库一次加载所有数据要快。再次感谢。你好,Aron,你的代码解决方案是最干净的,而且工作正常。但是,没有从linq转换到EF这样的事情。它们是不同的东西,在我们的例子中,我们使用EF和linq通过EF查询db。无论如何,感谢您的解决方案,选择g.Key并添加其中g.Key<12使整个情况有所不同。谢谢