如何加快此 Linq to SQL 查询的速度?
How can I speed up this Linq to SQL query?
所以,我有一个 returns 数据在 GridView 中使用的函数。它需要很长时间才能完成(大约 25 秒)。我觉得我写的很烂,我需要优化它让它运行得更快。
这是代码:
var pingresult = from p in db.GetTable<tblTBHealthPing>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthPingTime).FirstOrDefault();
var healthresult = from p in db.GetTable<tblTBHealthHeartbeat>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthHeartbeatTime).FirstOrDefault();
var query = (from t in TrackingBoardPCs()
where t.TrackingGroup == groupName
select new TrackingComputer
{
ComputerName = t.ComputerAsset,
IPAddress = t.ComputerIP,
Location = t.Location,
Pingable = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingResult).FirstOrDefault() ?? false,
PingTime = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingTime).FirstOrDefault() ?? DateTime.Now.AddDays(-100),
Username = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentUser).FirstOrDefault(),
CurrentWindow = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentWindow).FirstOrDefault(),
Uptime = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthUptime).FirstOrDefault()
}).OrderBy(t => t.Pingable);
return query;
可能有更好的方法,即删除前两个变量(pingresult 和 healthresult)并以某种方式将它们引入主查询,但我不知道如何做。任何帮助都会很棒:)
我想,你的 pingresult
和 healthresult
类型 iqueryable
。所以你的代码将 db
这个车道:
PingTime = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingTime).FirstOrDefault() ?? DateTime.Now.AddDays(-100),
Username = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentUser).FirstOrDefault(),
CurrentWindow = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentWindow).FirstOrDefault(),
Uptime = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthUptime).FirstOrDefault()
如果您使用 ToList()
,您的数据获取本地内存应该会更快。也许你可以这样使用:
var pingresult = from p in db.GetTable<tblTBHealthPing>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthPingTime).ToList().FirstOrDefault();//ToList() gets data from db to local memory
var healthresult = from p in db.GetTable<tblTBHealthHeartbeat>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthHeartbeatTime).ToList().FirstOrDefault();//ToList() gets data from db to local memory
将子查询嵌入主查询绝对是个好主意。
这样做时,您会注意到它们总是通过 ComputerAsset
连接到 TrackingBoardPCs
记录,因此它们不需要 groupby
该字段。
这是 IMO 的等效查询:
var query =
from t in TrackingBoardPCs()
where t.TrackingGroup == groupName
join p in db.GetTable<tblTBHealthPing>() on t.ComputerAsset equals p.ComputerAsset
into pingInfo
join h in db.GetTable<tblTBHealthHeartbeat>() on t.ComputerAsset equals h.ComputerAsset
into heartbeatInfo
let p = pingInfo.OrderByDescending(p => p.HealthPingTime).FirstOrDefault()
let h = heartbeatInfo.OrderByDescending(p => p.HealthHeartbeatTime).FirstOrDefault()
let tc = new TrackingComputer
{
ComputerName = t.ComputerAsset,
IPAddress = t.ComputerIP,
Location = t.Location,
Pingable = p.HealthPingResult ?? false,
PingTime = p.HealthPingTime ?? DateTime.Now.AddDays(-100),
Username = h.HealthCurrentUser,
CurrentWindow = h.HealthCurrentWindow,
Uptime = h.HealthUptime
}
order by tc.Pingable
select tc;
所以,我有一个 returns 数据在 GridView 中使用的函数。它需要很长时间才能完成(大约 25 秒)。我觉得我写的很烂,我需要优化它让它运行得更快。
这是代码:
var pingresult = from p in db.GetTable<tblTBHealthPing>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthPingTime).FirstOrDefault();
var healthresult = from p in db.GetTable<tblTBHealthHeartbeat>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthHeartbeatTime).FirstOrDefault();
var query = (from t in TrackingBoardPCs()
where t.TrackingGroup == groupName
select new TrackingComputer
{
ComputerName = t.ComputerAsset,
IPAddress = t.ComputerIP,
Location = t.Location,
Pingable = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingResult).FirstOrDefault() ?? false,
PingTime = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingTime).FirstOrDefault() ?? DateTime.Now.AddDays(-100),
Username = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentUser).FirstOrDefault(),
CurrentWindow = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentWindow).FirstOrDefault(),
Uptime = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthUptime).FirstOrDefault()
}).OrderBy(t => t.Pingable);
return query;
可能有更好的方法,即删除前两个变量(pingresult 和 healthresult)并以某种方式将它们引入主查询,但我不知道如何做。任何帮助都会很棒:)
我想,你的 pingresult
和 healthresult
类型 iqueryable
。所以你的代码将 db
这个车道:
PingTime = (from p in pingresult where p.ComputerAsset == t.ComputerAsset select p.HealthPingTime).FirstOrDefault() ?? DateTime.Now.AddDays(-100),
Username = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentUser).FirstOrDefault(),
CurrentWindow = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthCurrentWindow).FirstOrDefault(),
Uptime = (from p in healthresult where p.ComputerAsset == t.ComputerAsset select p.HealthUptime).FirstOrDefault()
如果您使用 ToList()
,您的数据获取本地内存应该会更快。也许你可以这样使用:
var pingresult = from p in db.GetTable<tblTBHealthPing>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthPingTime).ToList().FirstOrDefault();//ToList() gets data from db to local memory
var healthresult = from p in db.GetTable<tblTBHealthHeartbeat>()
group p by p.ComputerAsset into g
select g.OrderByDescending(t => t.HealthHeartbeatTime).ToList().FirstOrDefault();//ToList() gets data from db to local memory
将子查询嵌入主查询绝对是个好主意。
这样做时,您会注意到它们总是通过 ComputerAsset
连接到 TrackingBoardPCs
记录,因此它们不需要 groupby
该字段。
这是 IMO 的等效查询:
var query =
from t in TrackingBoardPCs()
where t.TrackingGroup == groupName
join p in db.GetTable<tblTBHealthPing>() on t.ComputerAsset equals p.ComputerAsset
into pingInfo
join h in db.GetTable<tblTBHealthHeartbeat>() on t.ComputerAsset equals h.ComputerAsset
into heartbeatInfo
let p = pingInfo.OrderByDescending(p => p.HealthPingTime).FirstOrDefault()
let h = heartbeatInfo.OrderByDescending(p => p.HealthHeartbeatTime).FirstOrDefault()
let tc = new TrackingComputer
{
ComputerName = t.ComputerAsset,
IPAddress = t.ComputerIP,
Location = t.Location,
Pingable = p.HealthPingResult ?? false,
PingTime = p.HealthPingTime ?? DateTime.Now.AddDays(-100),
Username = h.HealthCurrentUser,
CurrentWindow = h.HealthCurrentWindow,
Uptime = h.HealthUptime
}
order by tc.Pingable
select tc;