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();
總結
- 上一篇: 文明短信用语28句
- 下一篇: SIM通信协议-传输协议