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();

  

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注