如何加速Linq to SQL查询?

时间:2016-03-14 06:11:05

标签: database linq linq-to-sql

所以,我有一个函数返回数据以供在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)并以某种方式将它们引入主查询,但我不知道如何。任何帮助都会很棒:)

2 个答案:

答案 0 :(得分:0)

我认为,您的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

答案 1 :(得分:0)

将子查询嵌入主查询中绝对是个好主意。

执行此操作时,您会注意到TrackingBoardPCs始终加入了ComputerAsset记录,因此他们不需要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;