我要优化的 Linq 查询:
var onlineData = (from od in peopleStatus.AsNoTracking().ToList()
let location = (from zone in db.RTLS_ZONEDTLS
where zone.zone_id == od.Person.Zone_ID
select zone.area).AsNoTracking().FirstOrDefault()
let zoneIdsArray = getZoneList((od.ZoneIds.ToArray()))
let fzones = zoneIdsArray.Select(z => z).Take(4)
select new OnlineDataInfoDTO
{
P_ID = od.Person.PERSONID,
T_ID = (int)od.Person.TAGID,
Z_ID = (od.Person.created_time >= startOfThisDay) ? (int)od.Person.Zone_ID : -1,
LOC = (location != null ? location : " "),
STATUS = (od.Person.created_time >= startOfThisDay) ? (int)od.Person.status : 6,
T_BAT_SIG_STR = (int)od.Person.TAG_SIGNALSTRENGTH,
B_BAT_SIG_STR = (int)od.Person.BS_SIGNALSTRENGTH,
T_BAT_STA_VAL = (int)od.Person.TAG_BATTERY_STATUS_VAL,
T_BAT_STA_PERCNT = (int)od.Person.TAG_BATTERY_STATUS_PERCNT,
BS_BAT_STA_VAL = (int)od.Person.BS_BATTERY_STATUS_VAL,
BS_BAT_STA_PER = (int)od.Person.BS_BATTERY_STATUS_PERCNT,
IN_TIME = (od.Person.INTIME).ToString(),
ALL_NOT_TME = (od.Person.ALLISNOTWELLTIME).ToString(),
P_TME = (od.Person.PANICTIME).ToString(),
NO_M_TME = (od.Person.NOMOTIONTIME).ToString(),
OUT_TME = (od.Person.OUT_TIME).ToString(),
TEMP_TME = (od.Person.TEMPEXCEEDTIME).ToString(),
LOW_BAT_TME = (od.Person.LOW_BATTERY_TIME).ToString(),
FOUT_TME = (od.Person.FOUT_TIME).ToString(),
LAST_UPDATE_TIME = (od.Person.LASTUPDATEDTIME).ToString(),
TEMP_VAL = (decimal)(od.Person.TEMP_VALUE),
NO_OF_OUT = (
from o in db.RTLS_FAULT_DTLS
where (o.faultno == (int)Constants.Faults.LowBattery)
where (startOfThisDay <= o.ORC_DATETIME && o.ORC_DATETIME <= todayEndDate)
where (o.PERSON_ID.ToLower() == od.Person.PERSONID.ToLower())
select o.fltname).Count(),
NO_OF_PANIC = (
from o in db.RTLS_FAULT_DTLS
where o.faultno == (int)Constants.Faults.Panic
where (startOfThisDay <= o.ORC_DATETIME && o.ORC_DATETIME <= todayEndDate)
where (o.PERSON_ID.ToLower() == od.Person.PERSONID.ToLower())
select o.fltname).Count(),
NO_OF_IN_ACTIVE = (
from o in db.RTLS_FAULT_DTLS
where o.faultno == (int)Constants.Faults.InActive
where (startOfThisDay <= o.ORC_DATETIME && o.ORC_DATETIME <= todayEndDate)
where (o.PERSON_ID == od.Person.PERSONID)
select o.fltname).Count(),
NO_OF_TEMP = (
from o in db.RTLS_FAULT_DTLS
where (o.faultno == (int)Constants.Faults.HighTemp || o.faultno == (int)Constants.Faults.LowTemp)
where (startOfThisDay <= o.ORC_DATETIME && o.ORC_DATETIME <= todayEndDate)
where (o.PERSON_ID == od.Person.PERSONID)
select o.fltname).Count(),
NO_OF_LBAT = (
from o in db.RTLS_FAULT_DTLS
where o.faultno == (int)Constants.Faults.LowBattery
where (startOfThisDay <= o.ORC_DATETIME && o.ORC_DATETIME <= todayEndDate)
where (o.PERSON_ID == od.Person.PERSONID)
select o.fltname).Count(),
LOCS = fzones.ToList()
}).ToList();
我的 getZoneList 方法如下所示,用于上述查询。
public int[] getZoneList(decimal[] zoneIdsArray)
{
int[] zoneIds = Array.ConvertAll(zoneIdsArray, x => (int)x);
List<int> list = zoneIds.ToList();
for (int c = 1; c < zoneIdsArray.Count(); c++)
{
if (zoneIdsArray[c] == zoneIdsArray[c - 1])
{
list.Remove((int)zoneIdsArray[c]);
}
}
return list.ToArray();
}
对于我的应用程序,我在 Visual Studio-2015 中使用 WebApi2 编写了一个 Web 服务,实体框架作为 ORM,Azure_SQL 作为后端。我观察到上面的 linq 查询需要最少 25 秒到最多 1.5 分钟来执行(使用 azure 门户的查询性能洞察工具来找到它)。随着时间的推移逐行注释和测试代码后,我开始知道
from od in peopleStatus.AsNoTracking().ToList()
这条线花费了很多时间(平均 55 秒)。我不能跳过转换为 List 以进一步使用。建议我应该怎么做来优化我的查询以减少我的整体周转时间。
最后,通过删除AsNoTracking().ToList(),我将查询执行时间从 55 秒减少到平均 4.5 秒。
执行时间过长的旧查询。
var onlineData = from od in peopleStatuc.AsNoTracking().ToList()
新查询使我的总周转时间大幅减少。
var onlineData = from od in peopleStats
我发现在执行子查询时,我不必要地将结果转换为列表(将结果转换为列表的时间随着记录的增加而增加),因此将其删除。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句