• EF的性能瓶颈


    通过EF以面向对象的方式操作数据库带来了一定的便利性,但是某些情况下不宜采用EF否则会遇到性能瓶颈。目前遇到的问题主要包括两个方面:批量的DB操作、从DB带出大数量计算再持久化。

    1、批量的DB操作

    EF对批量插入、更新等操作会通过构造多条SQL的方式传输给DB执行,当量大的时候会带来传输及执行(执行方式甚至语句可优化)上的时间浪费。

    (1)示例

    foreach (var photo in photos)
    {
    	//添加样本照片记录
    	var samplePhoto = new SamplePhoto()
    	{
    		SamplePhotoId = CommonBll.PR_GetSysKey(efContext, "SamplePhoto", "SamplePhotoId", venderId),
    		PhotoId = photo.PhotoId,
    		SourceId = sampleSourceInfo.SourceId,
    		IsAllot = 0,
    		JoinTime = now,
    		VenderId = venderId
    	};
    	samplePhotoRepository.Add(samplePhoto);

    (2)执行情况

    foreach里的add产生多条执行的SQL

    INSERT [dbo].[SamplePhoto]([SamplePhotoId], [PhotoId], [SourceId], [IsAllot], [JoinTime], [Height], [VenderId], [Width])
    VALUES (@0, @1, @2, @3, @4, NULL, @5, NULL)
    -- @0: '10001303' (Type = Int32)
    -- @1: '54A7075D-1797-438A-B068-981D89B78AEB' (Type = String, Size = -1)
    -- @2: '10001044' (Type = Int32)
    -- @3: '0' (Type = Int32)
    -- @4: '2018/10/9 7:19:10' (Type = DateTime2)
    -- @5: '1000' (Type = Int32)
    -- 正在 2018/10/9 7:21:10 +08:00
     执行
    -- 已在 46 毫秒内完成,结果为: 1
    
    INSERT [dbo].[SamplePhoto]([SamplePhotoId], [PhotoId], [SourceId], [IsAllot], [JoinTime], [Height], [VenderId], [Width])
    VALUES (@0, @1, @2, @3, @4, NULL, @5, NULL)
    -- @0: '10001304' (Type = Int32)
    -- @1: '63B78093-A0F1-4E2B-8973-BED22164EAF1' (Type = String, Size = -1)
    -- @2: '10001044' (Type = Int32)
    -- @3: '0' (Type = Int32)
    -- @4: '2018/10/9 7:19:10' (Type = DateTime2)
    -- @5: '1000' (Type = Int32)
    -- 正在 2018/10/9 7:21:10 +08:00
     执行
    -- 已在 34 毫秒内完成,结果为: 1
    
    INSERT [dbo].[SamplePhoto]([SamplePhotoId], [PhotoId], [SourceId], [IsAllot], [JoinTime], [Height], [VenderId], [Width])
    VALUES (@0, @1, @2, @3, @4, NULL, @5, NULL)
    -- @0: '10001305' (Type = Int32)
    -- @1: '8F40A68C-0207-4000-BAB0-654ACCCDEA30' (Type = String, Size = -1)
    -- @2: '10001044' (Type = Int32)
    -- @3: '0' (Type = Int32)
    -- @4: '2018/10/9 7:19:10' (Type = DateTime2)
    -- @5: '1000' (Type = Int32)
    -- 正在 2018/10/9 7:21:10 +08:00
     执行
    -- 已在 38 毫秒内完成,结果为: 1

    2、从DB带出大数量计算再持久化

    大数量量从DB传递到应用,计算后再从应用传递到DB,需要耗费大量的网络资源,时间会消耗在传输上。

    var sampleboxs = boxs.Where(T => T.SamplePhotoId == photo.SamplePhotoId).ToList();
    if (sampleboxs != null)
    {
    	foreach (var box in sampleboxs)
    	{
    		var samplePhotoBox = new SamplePhotoBox()
    		{
    			//BoxId = CommonBll.PR_GetSysKey(efContext, "SamplePhotoBox", "BoxId", venderId),
    			SamplePhotoId = samplePhoto.SamplePhotoId,
    			XMax = box.XMax,
    			XMin = box.XMin,
    			YMax = box.YMax,
    			YMin = box.YMin,
    			SkuCode = box.SkuCode
    		};
    		samplePhotoBoxRepository.Add(samplePhotoBox);
    	}
    }
    

    从DB带出sampleboxs再逐个遍历计算后Add到另一张表,如果sampleboxs的量足够大的时候,这个逻辑的执行时间会花费几十秒、几分钟...

     

    3、替代方式

    对于EF有可能出现性能瓶颈的地方可通过执行“存储过程”或“参数化执行原生SQL”解决。

    SqlParameter[] paras = new SqlParameter[3];
    paras[0] = new SqlParameter("@inspectId", inspectId);
    paras[1] = new SqlParameter("@userId", userId);
    paras[2] = new SqlParameter("@venderId", venderId);
    
    var result = efContext.Database.SqlQuery<string>(
    	  "EXEC dbo.PR_NewSkuSetSample @inspectId,@userId,@venderId", paras).First();
    

      

  • 相关阅读:
    生于忧患,死于安乐
    【网络流24题】骑士共存问题
    【网络流24题】最长不下降子序列问题
    【网络流24题】太空计划问题
    SG函数
    【网络流24题】餐巾计划问题
    【APIO2019】奇怪装置
    【HEOI2016/TJOI2016】游戏
    【SDOI2015】星际战争
    【CQOI2009】跳舞
  • 原文地址:https://www.cnblogs.com/hepc/p/9758274.html
Copyright © 2020-2023  润新知