问题场景

有一个很多条数据的数据库(数据源),在其中找出指定的项,这些项的 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 用得太随意导致的性能问题一则的更多相关文章

  1. log4j导致的性能问题

    问题背景 双十一零点时,有一个服务A(后文该服务都用A来代替)的tp99由平常的50ms左右突然彪到60000ms,导致调用端积累了几十W的数据,同时,也影响到了同一个docker上的其他服务.那为什 ...

  2. linux交换区使用过多导致的性能问题

    近日,我们开发发现有一台配置相同的服务器跑的特别慢,相同数据量的情况下,其他服务器只要跑10分钟,这台服务器要跑50分钟,经确认,所有的应用层配置参数都相同.上去之后,发现该服务器swap使用比较多, ...

  3. 分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据

    分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据 今天开发找我,说数据库insert不进数据,叫我看一下 他发了一个截图给我 然后我登录上服务器,发现了可疑的地方,而且这个数据库之前 ...

  4. ssas 为绑定指定的大小太小,导致一个或多个列值被截断

    错误信息:ssas 为绑定指定的大小太小,导致一个或多个列值被截断 如果更改了某个维度或是事实表的字段长度,在处理CUBE时提示此错误,我们要做以下更新: 1.刷新数据源视图. 2.打开多维数据集,查 ...

  5. WebSphere中数据源连接池太小导致的连接超时错误记录

    WebSphere中数据源连接池太小导致的连接超时错误记录. 应用连接超时错误信息: [// ::: CST] webapp E com.ibm.ws.webcontainer.webapp.WebA ...

  6. Base64实现测试,不要太相信apache-common的性能

    针对三种Base64实现: * 自已实现的 * JDK8的java.util.Base64 * apache-common的org.apache.commons.codec.binary.Base64 ...

  7. EntityFramework Core 3多次Include导致查询性能低之解决方案

    前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...

  8. nginx 缓存区太小导致后台Connection reset by peer 报错

    问题概述:图片bit 64生成数据流太大,导致小程序分享弹窗的二维码图片生成失败 后台报错: 排查: Client------>nginx------->h5------>nginx ...

  9. sqlt 之 分析 DB upgrade 导致SQL 性能下降 的方法 xplore

    https://blog.csdn.net/lukeUnique/article/details/79331779 https://mauro-pagano.com/2014/10/27/when-t ...

随机推荐

  1. Git的认识与使用

    Git教程 https://www.liaoxuefeng.com/wiki/896043488029600/897271968352576 Git与SVN区别 Git 不仅仅是个版本控制系统,它也是 ...

  2. Linux rpm包管理工具

    1.什么是rpm包 是一种编译好的二进制软件包,安装速度快. 2.rpm包命名 el6:软件包用于在Red Hat 6.x, CentOS 6.x, and CloudLinux 6.x进行安装 el ...

  3. win10企业版LTSC批量激活

    slmgr -ipk M7XTQ-FN8P6-TTKYV-9D4CC-J462D   slmgr -skms kms.03k.org slmgr -ato slmgr -dlv

  4. 个人第2次作业:熟悉使用Git工具

    GIT地址 https://github.com/dxg1999 GIT用户名 dxg1999 学号后五位 62317 个人博客 我的博客 作业链接 作业内容 项目作业的整个过程 作业背景 阿超家里的 ...

  5. centos7-cockpit

    yum install cockpit* -y systemctl start cockpit.service systemctl enable cockpit.service 修改默认端口9090 ...

  6. 201871010106-丁宣元 《面向对象程序设计(java)》第四周学习总结

    201871010106-丁宣元 <面向对象程序设计(java)>第四周学习总结 正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-da ...

  7. day35_8_19 数据库

    一.存储引擎 不同的数据应该有不同的处理机制 MySQL中也有不同的存储引擎: 1.InnoDB MySQL默认的存储引擎. innoDB比myisam存储数据要安全. innoDB支持事务. inn ...

  8. pom文件详解(自己没看过)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  9. C# 集合根据属性去重筛选

    1.单个属性去重筛选 //去重筛选 var ChgDtlVoList = datas.Where((x, i) => datas.FindIndex(z => z.ChgId == x.C ...

  10. sqler 2.2 发布了,支持定时任务以及触发器

    sqler 在10前发布了,2.2 添加了定时任务以及触发器(webhook),都是比较方便的功能, 同时我也修改了dockerfile, 做了构建,添加了功能支持,同时push 到了dockerhu ...