Сущность рамках отложенной загрузки сравнение производительности


Следующий код занимает около 20 секунд, чтобы запустить около 200 000 записей в таблице TaskLogs:

using (var db = new DAL.JobManagerEntities())
    {
        return db.TaskLogs.Select(taskLog => new TaskLog()
        {
            TaskLogID = taskLog.TaskLogID,
            TaskID = taskLog.TaskID,
            TaskDescription = taskLog.Task.TaskDescription,
            TaskType = (TaskType)taskLog.Task.TaskTypeID,
            RunID = taskLog.RunID,
            ProcessID = taskLog.ProcessID,
            JobID = taskLog.JobID,
            JobName = taskLog.Job.JobName,
            Result = taskLog.Result,
            StartTime = taskLog.StartTime,
            TimeTaken = taskLog.TimeTaken
        }).OrderByDescending(t => t.RunID).ThenByDescending(t => t.RunID).ThenByDescending(t => t.StartTime).ToList();
    }

Я подправил его, пока я не получил то, что работает быстрее. Вот где я получил:

            using (var db = new DAL.JobManagerEntities())
    {
        db.Configuration.LazyLoadingEnabled = false;
        var tasks = db.Tasks.ToList();
        var jobs = db.Jobs.ToList();
        var result = db.TaskLogs.Select(x => new TaskLog()
        {
            TaskLogID = x.TaskLogID,
            TaskID = x.TaskID,
            RunID = x.RunID,
            ProcessID = x.ProcessID,
            JobID = x.JobID,
            Result = x.Result,
            StartTime = x.StartTime,
            TimeTaken = x.TimeTaken
        }).OrderByDescending(t => t.RunID).ThenByDescending(t => t.StartTime).ToList();

        foreach (var r in result)
        {
            r.TaskDescription = tasks.Single(t => t.TaskID == r.TaskID).TaskDescription;
            r.TaskType = (TaskType)tasks.Single(t => t.TaskID == r.TaskID).TaskTypeID;
            r.JobName = jobs.Single(j => j.JobID == r.JobID).JobName;
        }
        return result;}

Которая проходит менее чем за 6 секунд такое же количество записей.

В TaskLog таблицы связывается с заданий и задач, таблиц следующим образом: enter image description here

Задания и задания таблицы будут иметь 100S и 1000-ые записи соответственно.

Есть ли что-нибудь еще я могу сделать для того, чтобы улучшить эффективность кода?



Комментарии
2 ответа

1) Не уверен, если это влияет на производительность, но ваш первый фрагмент кода имеет один порядок к по:

.OrderByDescending(t => t.RunID).ThenByDescending(t => t.RunID)

2) Вы могли бы улучшить производительность вашего кода секунд с "клиентский индексации" (с использованием словаря):

var tasksMap = tasks.ToDictionary(t => t.TaskID);
var jobsMap = jobs.ToDictionary(t => t.JobID);

foreach (var r in result)
{
var task = tasksMap[r.TaskID];
r.TaskDescription = task.TaskDescription;
r.TaskType = (TaskType)task.TaskTypeID;
r.JobName = jobsMap[r.JobID].JobName;
}

3
ответ дан 12 февраля 2018 в 08:02 Источник Поделиться

Вы можете сделать две вещи, чтобы скорость этого запроса:


  • использовать joinТак что весь запрос выполняется на сервере, и вам не придется работать над результатами снова с foreach петли

  • добавить .AsNoTracking() к каждой таблице, так что EF не должен создавать прокси-объекты для отслеживания изменений.

Вот пример, как это будет выглядеть, когда мы применяем оба предложения.

using (var db = new DAL.JobManagerEntities())
{
db.Configuration.LazyLoadingEnabled = false;

var result =
from taskLog in db.TaskLogs.AsNoTracking()
join task in db.Tasks.AsNoTracking() on taskLog.TaskID equals task.TaskID
join job in db.Jobs.AsNoTracking() on taskLog.JobID equals job.JobID
orderby taskLog.RunID descending, taskLog.StartTime descending
select new TaskLog
{
TaskLogID = taskLog.TaskLogID,
TaskID = taskLog.TaskID,
RunID = taskLog.RunID,
ProcessID = taskLog.ProcessID,
JobID = taskLog.JobID,
Result = taskLog.Result,
StartTime = taskLog.StartTime,
TimeTaken = taskLog.TimeTaken,
TaskDescription = task.TaskDescription,
TaskType = (TaskType)task.TaskTypeID,
JobName = job.JobName
};

return result.ToList();
}

2
ответ дан 13 февраля 2018 в 07:02 Источник Поделиться