C# linq sum 效率问题,求大神!!!

lewis@110 2015-07-14 10:42:35

1、 var lastYearMonth = from p in
(from r in queLastYearMonthData.AsEnumerable()
group r by new { jxbm = r.Key } into g
select new { g.Key, count = g.Sum(x => x.count),sale=g.Sum(x=>x.sale), jj = (g.Sum(x => x.sale) / (ct = g.Sum(x => x.count) == 0 ? 1 : g.Sum(x => x.count))) }).AsEnumerable()
where p.jj >= Convert.ToDecimal(prices[j]) && p.jj < Convert.ToDecimal(prices[j + 1])
select p;

2、 decimal lastYearMonthCount_TB = lastYearMonth.Sum(x=>x.count);
3、 decimal lastYearMonthSale_TB = lastYearMonth.Sum(x => x.sale);

问题如下:
第一句查询筛选 剩余 2K 多条数据,查询很快,不足1s
第二、三条语句实现 sum()时,效率很慢,2s左右
求解决方案!!!
...全文
767 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
ajianchina 2015-07-16
  • 打赏
  • 举报
回复
引用 16 楼 huagangwang 的回复:
小弟我是新手,学Linq 不精,如果我想转换 DataTable 数据 ,用 AsParallel 就会报错了,这个该怎么提效率!
如果涉及到联表查询或是查询中要共享一个变量,不要用并行查询的方式,因为并行查询的推进顺序不可控,容易出现异常或是结果错误,数据量不大也不要用并行查询,并行查询不是什么时候都能提高查询速度,在数据量大、查询逻辑简单并且查询过程中不需共享变量的时候可以采用这一方式,我说的共享变量指的是查询过程中这一变量值就在发生改变的变量。 要将转换为datatable,就将查询结果遍历填充到datatable对象,方法网上很多,自己可以找了看看。
lewis@110 2015-07-16
  • 打赏
  • 举报
回复
引用 15 楼 ajianchina 的回复:
[quote=引用 12 楼 huagangwang 的回复:] [quote=引用 6 楼 ajianchina 的回复:] 对的,楼主第一条基本上是啥也没干。tolist加上后第一条的时间会增长,但2、3会非常快。
如果这样,我想求 sum() 两个字段,相对于还是时间没有节省下来啊(需要tolis()两次)[/quote] 问题就集中在第一条语句,你的第一条语句可以理解为一个“查询计划”,没有实质的查询结果,第2、3条执行的时候重复了第1条的查询过程,并且我看你的第1条语句有较大的优化余地,先重新组织语句进行优化,如果数据量大,可以用PLINQ,如果不知道PLINQ为何物,集合后点出来看AsParallel的提示:),让你tolist就是让第一条执行取得实质的查询结果,然后第2、3条语句就从这一结果中再计算sum值,而无需执行前述的查询过程,这样通俗易懂了吧。[/quote] 小弟我是新手,学Linq 不精,如果我想转换 DataTable 数据 ,用 AsParallel 就会报错了,这个该怎么提效率!
lewis@110 2015-07-15
  • 打赏
  • 举报
回复
引用 6 楼 ajianchina 的回复:
对的,楼主第一条基本上是啥也没干。tolist加上后第一条的时间会增长,但2、3会非常快。
如果这样,我想求 sum() 两个字段,相对于还是时间没有节省下来啊(需要tolis()两次)
lewis@110 2015-07-15
  • 打赏
  • 举报
回复
引用 5 楼 sp1234 的回复:
如果我给你的这个程序规定一下效率测试指标,我会把1 设置为1秒之内,而把2和3设置为20毫秒以下。超过这个速度就算是不合格了。
现在的速度 一共 大概 1.5s,还能不能有提高,感觉不是太理想
ajianchina 2015-07-15
  • 打赏
  • 举报
回复
引用 12 楼 huagangwang 的回复:
[quote=引用 6 楼 ajianchina 的回复:] 对的,楼主第一条基本上是啥也没干。tolist加上后第一条的时间会增长,但2、3会非常快。
如果这样,我想求 sum() 两个字段,相对于还是时间没有节省下来啊(需要tolis()两次)[/quote] 问题就集中在第一条语句,你的第一条语句可以理解为一个“查询计划”,没有实质的查询结果,第2、3条执行的时候重复了第1条的查询过程,并且我看你的第1条语句有较大的优化余地,先重新组织语句进行优化,如果数据量大,可以用PLINQ,如果不知道PLINQ为何物,集合后点出来看AsParallel的提示:),让你tolist就是让第一条执行取得实质的查询结果,然后第2、3条语句就从这一结果中再计算sum值,而无需执行前述的查询过程,这样通俗易懂了吧。
moonwrite 2015-07-15
  • 打赏
  • 举报
回复
把.AsEnumerable() 去掉,多此一举 不要在原来的lastYearMonth 集合上sum,重新写 下面是重新写的原因: 2、 decimal lastYearMonthCount_TB = lastYearMonth.Sum(x=>x.count); 你自己只是要count,但在原来的基础上sum,他还是会去计算sale等~~~而你又没有用到,浪费了计算 因为Linq是延迟执行的 所以2还是和上面的linq整合,重新生成sql语句~ var lastYearMonth = (from p in (from r in queLastYearMonthData.AsEnumerable() group r by new { jxbm = r.Key } into g select new { g.Key, count = g.Sum(x => x.count),sale=g.Sum(x=>x.sale), jj = (g.Sum(x => x.sale) / (ct = g.Sum(x => x.count) == 0 ? 1 : g.Sum(x => x.count))) }).AsEnumerable() where p.jj >= Convert.ToDecimal(prices[j]) && p.jj < Convert.ToDecimal(prices[j + 1]) select p).ToList();//加载到内存中,那么2,3的计算速度是非常快的~ 如果数据不多时可以这么做~,但最好还是不要
  • 打赏
  • 举报
回复
引用 12 楼 huagangwang 的回复:
[quote=引用 6 楼 ajianchina 的回复:] 对的,楼主第一条基本上是啥也没干。tolist加上后第一条的时间会增长,但2、3会非常快。
如果这样,我想求 sum() 两个字段,相对于还是时间没有节省下来啊(需要tolis()两次)[/quote] 1执行.ToList代表结果已经查出来了,然后2,3就是在内存里操作了,哪里来两次ToList之说…… 也就是总共耗时1S左右 Linq是延迟执行的
threenewbee 2015-07-14
  • 打赏
  • 举报
回复
要想效率高,就要放在sql服务器上执行
lewis@110 2015-07-14
  • 打赏
  • 举报
回复
引用 5 楼 sp1234 的回复:
如果我给你的这个程序规定一下效率测试指标,我会把1 设置为1秒之内,而把2和3设置为20毫秒以下。超过这个速度就算是不合格了。
我遇见的问题好邪门,明明就100条数据,select 功能很快,一到 sum() 效率就明显慢下来了,我也不知道什么原因 lz能不能给一些建议
lewis@110 2015-07-14
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
如果1的结果不多(没有多到10万个结果),那么你把1的查询结果应该一次性地 ToList 存到一个结果集合中。而不应该(至少)延迟计算3遍查询。 实际上即使对于近万个1查询出来的对象(何况你还根本没有这么多对象),在内存中汇总一下某个属性的合计,我相信你的2和3都应该是在100毫秒以下就计算完了。
lz 说的对,我少一个 sum(),也就节省了 1-2s,这样如果循环查询的多了,也就节省了很大一部分时间,!谢谢
  • 打赏
  • 举报
回复
超过这个速度就算是不合格了 --> 超过这个速度限制就算是不合格了 当然你可以自己调整实际值。但是最主要地,这在于根本方法、基础流程的不同,而不是简单地优化一两条语句的问题。
ajianchina 2015-07-14
  • 打赏
  • 举报
回复
对的,楼主第一条基本上是啥也没干。tolist加上后第一条的时间会增长,但2、3会非常快。
  • 打赏
  • 举报
回复
如果我给你的这个程序规定一下效率测试指标,我会把1 设置为1秒之内,而把2和3设置为20毫秒以下。超过这个速度就算是不合格了。
  • 打赏
  • 举报
回复
如果1的结果不多(没有多到10万个结果),那么你把1的查询结果应该一次性地 ToList 存到一个结果集合中。而不应该(至少)延迟计算3遍查询。 实际上即使对于近万个1查询出来的对象(何况你还根本没有这么多对象),在内存中汇总一下某个属性的合计,我相信你的2和3都应该是在100毫秒以下就计算完了。
lewis@110 2015-07-14
  • 打赏
  • 举报
回复
引用 2 楼 ajianchina 的回复:
PLINQ再比较一下
PLINQ 没有使用过,具体怎么使用啊
ajianchina 2015-07-14
  • 打赏
  • 举报
回复
PLINQ再比较一下
  • 打赏
  • 举报
回复
Sum快不起来的,必须一个个处理下去,或者你可以用将两个Sum在两个线程里面并行计算,这样就只要1S多点了

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧