0

我有一个查询,它处理从各种表中提取的大约 500 条记录,分组然后汇总(如果这是一个词)到工作报告中。一切正常,但运行此报告大约需要 30 秒,而且我收到了用户的投诉。

有问题的程序是这样的:

    public static List<LabourEfficiencies> GetLabourEfficienciesByTimeSheet(DateTime dateFrom, DateTime dateTo)
    {
        CS3Entities ctx = new CS3Entities();

        //get all relevant timesheetline items
        var tsItems = from ti in ctx.TimeSheetItems
                      where ti.TimeSheetHeader.Date >= dateFrom && ti.TimeSheetHeader.Date <= dateTo && ti.TimeSheetHeader.TimeSheetCategory != "NON-PROD"
                      select new TimesheetLine
                      {
                          TimesheetNo = ti.TimeSheetNo,
                          HoursProduced = ti.HoursProduced,
                          HoursProducedNet = ti.HoursProducedNet,
                          ItemID = ti.ItemID,
                          ProcessID = ti.ProcessID,
                          ProcessDuration = ti.ProcessDuration,
                          DowntimeHours = 0M
                      };

        //get all relevant downtimeline items
        var tsDownT = from dt in ctx.DowntimeItems
                      where dt.TimeSheetHeader.Date >= dateFrom && dt.TimeSheetHeader.Date <= dateTo && dt.TimeSheetHeader.TimeSheetCategory != "NON-PROD"
                      select new TimesheetLine
                      {
                          TimesheetNo = dt.TimeSheetNo,
                          HoursProduced = 0M,
                          HoursProducedNet = 0M,
                          ItemID = "",
                          ProcessID = "",
                          ProcessDuration = 0M,
                          DowntimeHours = dt.DowntimeHours
                      };

        //combine them into single table
        var tsCombi = tsItems.Concat(tsDownT);

        var flatQuery = (from c in tsCombi
                        join th in ctx.TimeSheetHeaders on c.TimesheetNo equals th.TimeSheetNo
                        select new
                                   {
                                       th.TimeSheetNo,
                                       th.EmployeeNo,
                                       th.TimeSheetCategory,
                                       th.Date,
                                       c.HoursProduced,
                                       c.ProcessDuration,
                                       th.HoursWorked,
                                       c.HoursProducedNet,
                                       c.DowntimeHours,
                                       c.ItemID
                                       });

        //add employee details & group by timesheet no (1 line per timesheet no)
        //NB. FnTlHrs checks whether there are any indirect hrs & deducts them if there are
        var query =  flatQuery.GroupBy(f => f.TimeSheetNo).Select(g => new LabourEfficiencies
                                                                            {
                                                                                Eno = g.FirstOrDefault().EmployeeNo,
                                                                                Dept =g.FirstOrDefault().TimeSheetCategory,
                                                                                Date = g.FirstOrDefault().Date,
                                                                                FnGrHrs =g.Where(w =>w.TimeSheetCategory == "FN" &&!w.ItemID.StartsWith("090")).Sum(h => h.HoursProduced),
                                                                                FnTlHrs =g.Where(w =>w.ItemID.StartsWith("090")).Sum(h => h.ProcessDuration) >0? (g.FirstOrDefault(w =>w.TimeSheetCategory =="FN").HoursWorked) -(g.Where(w =>w.ItemID.StartsWith("090")).Sum(h =>h.ProcessDuration)): g.FirstOrDefault(w =>w.TimeSheetCategory =="FN").HoursWorked,
                                                                                RmGrHrs =g.Where(w =>w.TimeSheetCategory == "RM").Sum(h => h.HoursProduced),RmGrHrsNet =g.Where(w =>w.TimeSheetCategory == "RM").Sum(h => h.HoursProducedNet),
                                                                                RmTlHrs =g.FirstOrDefault(w =>w.TimeSheetCategory == "RM").HoursWorked,
                                                                                MpGrHrs =g.Where(w =>w.TimeSheetCategory =="MATPREP").Sum(h => h.HoursProduced),
                                                                                MpTlHrs =g.FirstOrDefault(w =>w.TimeSheetCategory =="MATPREP").HoursWorked,
                                                                                DtHrs = g.Sum(s => s.DowntimeHours),
                                                                                Indirect =g.Where(w =>w.ItemID.StartsWith("090")).Sum(h => h.ProcessDuration)
                                                                            });

        return query.ToList();
    }

前几位只是收集数据,最后一个查询是过程的“肉”,需要时间。

我相当肯定我做了一些可怕的事情,因为它吐出的 SQL 很糟糕,但对于我的生活,我看不到如何改进它。

任何提示都非常感谢。

戈登

4

1 回答 1

1

您的表达式在 IQueriable 编译和 SQL 服务器查询优化中都得到了优化,即使在这里也需要很长时间。您很可能不需要执行计划更快的列索引。将您呈现的 SQL 表达式复制/粘贴到 SSMS,运行它并查看实际计划。如果需要,优化数据库结构(放置索引)。否则,您将获得大量数据,从而使流程变慢。

于 2013-11-13T15:29:23.923 回答