侧边栏壁纸
博主头像
Komi博主等级

WizMan Komi

  • 累计撰写 30 篇文章
  • 累计创建 43 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

记一次线上查询变慢的重大Bug (IQueryable vs Enumerable)

Komi
2022-08-17 / 0 评论 / 0 点赞 / 73 阅读 / 783 字
温馨提示:
内容仅供参考,实际使用需根据自身条件进行调整与删改

事情起因

var vocDataList = newContext.VocData.Where(s => s.Convert_Start_Date >= value._StartDate && s.Convert_Start_Date <= value._EndDate);

foreach (var info in carPlans.SelectMany(item => item))
{
    if (value._IsOld)
    {
        gpsFunc.GetHighFreqAddresses(vocDataList);
    }
    else
    {                        
        gpsFunc.GetHighFreqAddressesNew(vocDataList);
    }
}

上面的这段代码乍一看是没有什么异样的 但后来发现 查询时间奇慢 耗时接近了20分钟,根据我们的前端同事反映 原来的查询时间不过最多一分半,于是 我便着手查看问题所在

切入

上面的变量 vocDataList 的类型推断为IQueryable 经过网上的相关资料查询后发现IQueryable属于延迟加载的 也就是说当前的变量只算是声明了SQL表达式 并没有直接去访问数据库查询数据 只有在之后的程序中引用到该变量才算正式执行 相当于是 每循环一次就需要去访问一次数据库

01.png
IQueryable源码

02.png
Enumerable源码

如上图所示 讲白了: IEnumerable基于内存中运算,IQueryable基于远程运算
1.Func<>谓词表达式,就是一个委托,委托一旦调用,就立即执行了,将执行结果保存在内存中 这也就是为什么最后将查询结果IQueryable直接转换为List 作为静态的实体列表查询
2.Expression是一个表达式,会存储拼接表达式树,直到在运行期最终执行

推荐阅读

https://www.daimajiaoliu.com/daima/610ae7caf434c08

0

评论区