Linq 用得太随意导致的性能问题一则
问题场景
有一个很多条数据的数据库(数据源),在其中找出指定的项,这些项的 ID 位于 给定的列表中,如 TargetList 中。
private readonly IDictionary<string, int> _testSource = new Dictionary<string, int>();
private readonly IList<string> _targetStringList = new List<string>();
直观简洁的 Linq 写法
public long TestFindByLinq()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = _testSource.Where(s => _targetStringList.Contains(s.Key)).Select(s=>s.Value).ToList();
// IList<int> theResultData2 = _targetStringList.Select(f => _testSource[f]).ToList();
sw.Stop();
Console.WriteLine($"[TestFindByLinq] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count} \n");
return sw.ElapsedTicks;
}
问题在于,如果这么写,将要遍历整个源数据,性能受影响。
看起来麻烦,但性能好很多的写法
public long TestFindByForEach()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = new List<int>();
foreach (string target in _targetStringList)
{
int data = _testSource[target];
theResultData.Add(data);
}
sw.Stop();
Console.WriteLine($"[TestFindByForEach] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count}\n");
return sw.ElapsedTicks;
}
性能相差多少呢?
从 100000 条数据中,找 6354 条数据。

差不多是 1000 倍以上的性能差距。
有什么启发吗?
Linq 性能不好,有时候可能只是 Linq 写得不好,Linq 写起来很方便,但如果写法中涉及到的查询方式,需要遍历全部数据,性能必然受到影响,如果还要多次遍历全部内容,那就更可怕了。
修正
以上测试考虑问题确实是不全面的,详情可以看评论区大佬的回复。
1 如果知道一定包含,可以用
var testData = _targetStringList.Select(f => _testSource[f]).ToList();
2 可以使用 hashSet
var testData = _testSource.Where(s => _targetStringList.Contains(s.Key)).ToList();
// 在原有的基础上,改动最小可以用HashSet
var hashSet = _targetStringList.ToHashSet();
var testData = _testSource.Where(s => hashSet.Contains(s.Key)).ToList();
// by 评论区 @玩命夜狼
感谢各位大佬指正。
原文链接 : https://www.cnblogs.com/jasongrass/p/10797795.html
附:测试完整源码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace GrassDemoPark.CoreConsoleApp
{
class LinqTest
{
private readonly IDictionary<string, int> _testSource = new Dictionary<string, int>();
private readonly IList<string> _targetStringList = new List<string>();
public LinqTest()
{
for (int i = 0; i < 100000; i++)
{
string guid = Guid.NewGuid().ToString();
_testSource.Add(guid, i);
if (guid.StartsWith("5"))
{
_targetStringList.Add(guid);
}
}
}
public long TestFindByLinq()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = _testSource.Where(s => _targetStringList.Contains(s.Key)).Select(s=>s.Value).ToList();
// IList<int> theResultData2 = _targetStringList.Select(f => _testSource[f]).ToList();
sw.Stop();
Console.WriteLine($"[TestFindByLinq] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count} \n");
return sw.ElapsedTicks;
}
public long TestFindByForEach()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = new List<int>();
foreach (string target in _targetStringList)
{
int data = _testSource[target];
theResultData.Add(data);
}
sw.Stop();
Console.WriteLine($"[TestFindByForEach] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count}\n");
return sw.ElapsedTicks;
}
}
}
Linq 用得太随意导致的性能问题一则的更多相关文章
- log4j导致的性能问题
问题背景 双十一零点时,有一个服务A(后文该服务都用A来代替)的tp99由平常的50ms左右突然彪到60000ms,导致调用端积累了几十W的数据,同时,也影响到了同一个docker上的其他服务.那为什 ...
- linux交换区使用过多导致的性能问题
近日,我们开发发现有一台配置相同的服务器跑的特别慢,相同数据量的情况下,其他服务器只要跑10分钟,这台服务器要跑50分钟,经确认,所有的应用层配置参数都相同.上去之后,发现该服务器swap使用比较多, ...
- 分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据
分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据 今天开发找我,说数据库insert不进数据,叫我看一下 他发了一个截图给我 然后我登录上服务器,发现了可疑的地方,而且这个数据库之前 ...
- ssas 为绑定指定的大小太小,导致一个或多个列值被截断
错误信息:ssas 为绑定指定的大小太小,导致一个或多个列值被截断 如果更改了某个维度或是事实表的字段长度,在处理CUBE时提示此错误,我们要做以下更新: 1.刷新数据源视图. 2.打开多维数据集,查 ...
- WebSphere中数据源连接池太小导致的连接超时错误记录
WebSphere中数据源连接池太小导致的连接超时错误记录. 应用连接超时错误信息: [// ::: CST] webapp E com.ibm.ws.webcontainer.webapp.WebA ...
- Base64实现测试,不要太相信apache-common的性能
针对三种Base64实现: * 自已实现的 * JDK8的java.util.Base64 * apache-common的org.apache.commons.codec.binary.Base64 ...
- EntityFramework Core 3多次Include导致查询性能低之解决方案
前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...
- nginx 缓存区太小导致后台Connection reset by peer 报错
问题概述:图片bit 64生成数据流太大,导致小程序分享弹窗的二维码图片生成失败 后台报错: 排查: Client------>nginx------->h5------>nginx ...
- sqlt 之 分析 DB upgrade 导致SQL 性能下降 的方法 xplore
https://blog.csdn.net/lukeUnique/article/details/79331779 https://mauro-pagano.com/2014/10/27/when-t ...
随机推荐
- 网关地址和网关IP是什么,他们有什么关系?
2019-12-19 新用户541... 转自 小糊涂大神 修改 通常情况下,一台终端上网必须设置IP地址.子网掩码.网关IP地址,终端IP地址与网关IP属于同一个网段,网关IP是终端访问外网 ...
- JS高阶---继承模式(借用构造函数继承+组合继承)
(1)借用构造函数继承 案例如下: 验证: (2)组合继承 案例如下: 验证如下: 结果如右图所示 . .
- 第14节_BLE协议ATT层
下面这个图是BLE协议各层跟医院的各个科室的类比图: 跟医院类比,ATT层就是化验室,通过它可以得到各种检查结果──属性.这些检查结果之间有什么联系,它们组合起来体现了什么,化验室是不知道的,这些得由 ...
- Linux命令——trap
简介 trap是shell内置命令,它对硬件信号和其他事件做出响应.trap定义并激活信号处理过程,信号处理过程是当shell接收信号或其他特殊条件时要运行的处理过程. 语法 trap [-lp] [ ...
- SQLAlchemy(1)
介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据API执行SQL并获取 ...
- python -m pip install --upgrade pip
升级pip后报错 TypeError: 'module' object is not callable 原因 存在两个版本的pip 先把原先版本的卸载了: python -m pip uninstal ...
- zz独家专访AI大神贾扬清:我为什么选择加入阿里巴巴?
独家专访AI大神贾扬清:我为什么选择加入阿里巴巴? Natalie.Cai 拥有的都是侥幸,失去的都是人生 关注她 5 人赞同了该文章 本文由 「AI前线」原创,原文链接:独家专访AI大神贾扬清:我 ...
- BOI 2003 团伙
洛谷 P1892 [BOI2003]团伙 洛谷传送门 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋 ...
- [LeetCode] 269. Alien Dictionary 另类字典
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- 计时任务之StopWatch
StopWatch对应的中文名称为秒表,经常我们对一段代码耗时检测的代码如下: long startTime = System.currentTimeMillis(); // 业务处理代码 doSom ...