如何加快此 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)并以某种方式将它们引入主查询,但我不知道如何做。任何帮助都会很棒:)

我想,你的 pingresulthealthresult 类型 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;