lamdba 性能測試 大數據內存查找
阿新 • • 發佈:2018-07-10
相關 fin () status ssa mdb 速度 全局 提升
lamdba 性能
由於工作中需要對大量數據進行快速校驗,試驗采用讀入內存列表采用lamdba查找來實現。
詳細需求:實際讀入內存數據 50W條記錄主集數據,還包含約20個子集,子集最大記錄數300W條記錄。讀入內存,校驗出結果5分鐘之內完成。
測試數據讀入內存後占用約2-3G內存。這裏測試了多線程讀取數據,但提速效果並不明顯。SQLServer有自己的SQL執行排隊機制(讀入數據過程遇到一個小插曲,讀入速度慢,占用內存大,無意中發現是把人員照片流也讀入了內存。實現處理數據過程並不需要照片信息。去掉後速度提升很大,占用內存也縮小很多,以後遇到類似操作應提前排除這類情況了)
數據校驗腳本由另一個同事寫的,開始拿到腳本丟進去測試,結果半個小時也沒反應。果斷結束進程。然後就是痛苦的優化過程,曾經懷疑這樣的方式行不通。差不多用了兩周時間,達到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 => personIds2.IndexOf(x.PersonID)) 最快 A01.FindAll(x => x.PersonID.In(personIds)) 第二 A01.FindAll(x => personIds2.Contains(x.PersonID)) 第二 A01.FindAll(x => personIds2.Exists(p=>p == x.PersonID)) 最慢 聯合查詢 速度快 var query = (from A14 in PersonData.A14 join A01 in PersonData.A01 on A14.PersonID equals A01.PersonID select new { A14.PersonID, 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秒.
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 => personIds2.IndexOf(x.PersonID)) 最快 A01.FindAll(x => x.PersonID.In(personIds)) 第二 A01.FindAll(x => personIds2.Contains(x.PersonID)) 第二 A01.FindAll(x => personIds2.Exists(p=>p == x.PersonID)) 最慢 聯合查詢 速度快 var query = (from A14 in PersonData.A14 join A01 in PersonData.A01 on A14.PersonID equals A01.PersonID select new { A14.PersonID, 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秒.
lamdba 性能測試 大數據內存查找