问题场景

有一个很多条数据的数据库(数据源),在其中找出指定的项,这些项的 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. kolla部署openstack allinone,报错 ImportError: cannot import name decorate

    使用 kolla-ansible 部署 opnenstack:stein,最后无法导入变量脚本,报错信息如下: [root@kolla ~]# . /etc/kolla/admin-openrc.sh ...

  2. vue中webpack的配置理解

    当我们需要和后台分离部署的时候,必须配置config/index.js: 用vue-cli 自动构建的目录里面  (环境变量及其基本变量的配置) var path = require('path') ...

  3. Linux---文件压缩与解压缩命令

    压缩格式: zip.gz.bz2.tar .tar.gz.tar.bz2.tar.xz.xz.z 最常用的是.tar.gz格式和.tar.bz2格式 1.zip格式 命令  说明  zip 压缩文件名 ...

  4. GitHub操作(五)

    GitHub 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub. 1. 打开浏览器,输入GitHub的网址https://github.co ...

  5. ESP8266 LUA脚本语言开发: 准备工作-LUA开发说明

    前言 开发Lua需要使用这个软件 注:该软件需要按照JDK  即 JAVA虚拟机,如果没有安装过JDK,请先看JDK安装教程安装JDK USB线连接开发板接入电脑 选择自己的串口号 波特率115200 ...

  6. [BJOI2019]光线(DP)

    降智了…… 当你走头无路的时候就应该知道瞎搞一个DP: $p[i]$ 表示光射入第 $1$ 块玻璃时,从第 $i$ 块玻璃出去的光量. $q[i]$ 表示光射入第 $i$ 块玻璃时,从第 $i$ 块玻 ...

  7. [探究] [Luogu4550]收集邮票的概率意义

    自认为这道题是一道比较简单的扩展题--?此处采用了和别的题解思路不同的,纯概率意义上的解法. 首先考虑一个简化版问题: 每次随机一个\([1,n]\)的整数,问期望几次能凑出所有数 这东西我写过一个b ...

  8. [LeetCode] 50. Pow(x, n) 求x的n次方

    Implement pow(x, n), which calculates x raised to the power n(xn). Example 1: Input: 2.00000, 10 Out ...

  9. 黑科技!两行代码完美解决:同时设置overflow-x:hidden,overflow-y:visible无效的问题

    不废话,直接上代码 <!DOCTYPE html> <html> <head> <style> body { padding: 0; margin: 0 ...

  10. 安装Oracle 11g时遇到“【INS-13001】此环境不满足最低配置”的问题解决

    一.问题如下: win10一般容易出现这个问题,可能是版本兼容的关系.  二.解决方法: 在Oracle 11g解压出的文件夹下寻找cvu_prereq.xml文件: 路径:database\stag ...