• lamdba 性能测试 大数据内存查找


     
    由于工作中需要对大量数据进行快速校验,试验采用读入内存List实体采用lamdba查找来实现。
    实际需求:实际读入内存数据 50W条记录主集数据,还包含约20个子集,子集最大记录数300W条记录。读入内存,校验出结果5分钟之内完成。
    测试数据读入内存后占用约2-3G内存。这里测试了多线程读取数据,但提速效果并不明显。SQLServer有自己的SQL执行排队机制(读入数据过程遇到一个小插曲,读入速度慢,占用内存大,无意中发现是把记录照片流也读入了内存。实际处理数据过程并不需要照片信息。去掉后速度提升很大,占用内存也缩小很多,以后遇到类似操作应提前排除这类情况了)
    数据校验脚本由另一个同事写的,大约有500个校验,实体字段合法性校验,及主集子集关联检验。开始拿到脚本丢进去测试,结果半个小时也没反应。果断结束进程。然后就是痛苦的优化过程,曾经怀疑这样的方式行不通。差不多用了两周时间,达到5000个主集信息10秒以内完成。50W数据也在3-5分钟完成。最后完成100个并发测试。校验结果正常返回。一切OK现已正常上线使用。
     
    以下是在本次数据校验实现过程中总结出来应注意的一些地方。

    1、由原来数据库校验改为内存校验,内存速度更快,数据库校验还会带来并发等待,死锁等问题。
    2、加载数据可以采用多线程加载
    3、主键使用整形加快查询速度 这一点特别重要,速度提升上千倍。
    4、采用lamdba表达式查找数据 用联合查询代替for循环
    5、根据数据量的大小采用分别采取线性查找或二分查找提高查询速度
    6、共用数据只取一次,在整个校验中全局使用。
    并发测试 时发现 静态类中的静态属性不是安全的 因为静态类在内存中只有一份 去掉static 后多线程测试正常
     
    以下为测试数据,及相关说明,可以直接忽略。感兴趣的的可以看看。

    1、7万条记录
    A01.FindAll(x => !x.PersonStatus.In("01", "02", "03", "04"))
    循环查找,共加载15298人,耗时:0.019519秒.
    A01.FindAll(x => !(x.PersonStatus == "01" || x.PersonStatus == "02" || x.PersonStatus == "03" || x.PersonStatus == "04"))
    循环查找,共加载15298人,耗时:0.0284169秒.
     
    2、3.3万条记录 x.CodeID == "ZB01"的有3300条记录
    Codes.FindAll(x => x.CodeID == "ZB01" && (x.CodeItemName == "市辖区" || x.CodeItemName == "县"))
    循环查找,共加载287人,耗时:0.0139286秒.
    Codes.FindAll(x => x.CodeID == "ZB01" && (x.CodeItemName.In("市辖区", "县")))
    循环查找,共加载287人,耗时:0.0230568秒.
     
    3、4000条记录 codeIds有3300条记录
    personTableList.A01.FindAll(x => !x.A0114.In(codeIds));
    A01 4000条记录 循环查找,共加载0人,耗时:0.1066983秒.
    A01 7万条记录 循环查找,共加载0人,耗时:1.7386399秒.
    foreach (var A01 in personTableList.A01)
                {
                    if (!codes.Exists(x => x.CodeItemID == A01.A0114))
                    {
                        persons.Add(A01);
                    }
                }
     
    上面形式代码,两个列表都是7W条记录时
    循环查找,共加载75601人,耗时:55.4800723秒.
    循环查找,共加载75601人,耗时:107.4412256秒.
     
    3、
    A01.FindAll(x => x.W0111G == "")
    循环查找,共加载183人,耗时:0.0039961秒.
    A01.FindAll(x => x.W0111G.IsSame(""))
    循环查找,共加载183人,耗时:0.0307353秒.
     
     
    A01.FindAll(x => ids2.IndexOf(x.PersonID))  最快
    A01.FindAll(x => x.PersonID.In(personIds)) 第二
    A01.FindAll(x => ids2.Contains(x.PersonID))  第二 
    A01.FindAll(x => ids2.Exists(p=>p == x.PersonID)) 最慢
     
    联合查询 速度快
    var query = (from A14 in DataList.A14
                             join A01 in DataList.A01
                               on A14.ID equals A01.ID
                             select new { A14.ID, A14.A1407, A01.A0141 }).ToList();
                personIds = query.FindAll(x => x.A0141 > x.A1407)
    非常重要 主键字段 整形字段比字符串快上百倍
     
     
    线性查找:Contains,Find,IndexOf都是线性查找。
    二分查找:BinarySearch,因为二分查找必须是对有序数组才有效,所以查找前要调用List的Sort方法。
    结论:如果List项的个数比较小,用线性查找要略快于二分查找,项的个数越多二分算法优势越明显。可根据实际情况选用适合的查找方式。
    测试数据2条
    耗时:0.0186627秒.
    二分耗时:0.0356611秒.
     
     
  • 相关阅读:
    GIS重要概念与术语——矢量数据分析
    后台获取存储过程返回的数据(转)
    java集合map,set,list区别
    安装jdk配置环境变量并测试java
    使用JAVA读写Properties属性文件
    对象(含有java.util.Date),集合等转换成json
    SSH自我理解实质
    Hibernate中createCriteria即QBC查询的详细用法
    用Java递归来求N的阶层
    java this的使用
  • 原文地址:https://www.cnblogs.com/DevMuYuer/p/9293297.html
Copyright © 2020-2023  润新知