Мне нужно запросить несколько столбцов из нескольких таблиц с помощью EF. Все идет хорошо и с хорошей производительностью, когда я не включаю отношения M-M в запрос выбора.Entity Framework 6 Производительность запроса (отношение M-M)
запросов с ММ Отношения:
result = (from s in db.Member
.Include(i => i.Category)
.Include(i => i.MemberWorkEntity)
.Include(i => i.Status)
.Include(i => i.DiscountMethod)
.Where(i => i.C_deleted == null)
select new MemberDTO
{
memberNumber = s.memberNumber,
name = s.name,
status = s.Status.name,
email = s.email,
phone = s.phone,
mobile = s.mobile,
fax = s.fax,
workEntity = (from e in db.WorkEntity.Where(i => i.workEntityLevelID == 2)
join sc in s.MemberWorkEntity on e.workEntityID equals sc.workEntityID
select e.name).FirstOrDefault(),
category = s.Category.name,
discountMethod = s.DiscountMethod.name,
delegate = s.delegate ? "Yes" : "No",
leader = s.leader ? "Yes" : "No"
}).AsNoTracking().ToList<MemberDTO>();
30000 время выполнения записи (мс):
|1st Execution: 1376
|2nd Execution: 160
|3rd Execution: 145
Запрос без ММ Отношения:
result = (from s in db.Member
.Include(i => i.Category)
.Include(i => i.MemberWorkEntity)
.Include(i => i.Status)
.Include(i => i.DiscountMethod)
.Where(i => i.C_deleted == null)
select new MemberDTO
{
memberNumber = s.memberNumber,
name = s.name,
status = s.Status.name,
email = s.email,
phone = s.phone,
mobile = s.mobile,
fax = s.fax,
//removed M-M Relationship Query
category = s.Category.name,
discountMethod = s.DiscountMethod.name,
delegate = s.delegate ? "Yes" : "No",
leader = s.leader ? "Yes" : "No"
}).AsNoTracking().ToList<MemberDTO>();
30000 записей время исполнения (мс) :
|1st Execution: 1286
|2nd Execution: 79
|3rd Execution: 67
Почему такое различие (в среднем, медленнее в среднем)? Как повысить производительность запросов?
UPDATE: Отношения между членами и WorkEntity
UPDATE: Обновлен мой запрос на основе @ AndreFilimon-х внушения:
IEnumerable<WorkEntity> workEntities = db.WorkEntity.AsNoTracking().Where(i => i.workEntityLevelID == 2);
result = (from s in db.Member
.Include(i => i.Category)
.Include(i => i.Status)
.Include(i => i.DiscountMethod)
.Where(i => i.C_deleted == null)
select new MemberDTO
{
memberNumber = s.memberNumber,
name = s.name,
status = s.Status.name,
email = s.email,
phone = s.phone,
mobile = s.mobile,
fax = s.fax,
workEntity = (from e in workEntities
join sc in s.MemberWorkEntity on e.workEntityID equals sc.workEntityID
select e.name).FirstOrDefault(),
category = s.Category.name,
discountMethod = s.DiscountMethod.name,
delegate = s.delegate ? "Yes" : "No",
leader = s.leader ? "Yes" : "No"
}).AsNoTracking().ToList<MemberDTO>();
30000 время выполнения записи (мс):
|1st Execution: 1364
|2nd Execution: 122
|3rd Execution: 120
UPDATE: Добавлен простой индекс к моему столу членов в качестве @agfc предложил:
IEnumerable<WorkEntity> workEntities = db.WorkEntity.AsNoTracking().Where(i => i.workEntityLevelID == 2);
result = (from s in db.Member
.Include(i => i.Category)
.Include(i => i.Status)
.Include(i => i.DiscountMethod)
.Where(i => i.C_deleted == null)
select new MemberDTO
{
memberNumber = s.memberNumber,
name = s.name,
status = s.Status.name,
email = s.email,
phone = s.phone,
mobile = s.mobile,
fax = s.fax,
workEntity = (from e in workEntities
join sc in s.MemberWorkEntity on e.workEntityID equals sc.workEntityID
select e.name).FirstOrDefault(),
category = s.Category.name,
discountMethod = s.DiscountMethod.name,
delegate = s.delegate ? "Yes" : "No",
leader = s.leader ? "Yes" : "No"
}).AsNoTracking().ToList<MemberDTO>();
30000 записей Время выполнения (мс):
|1st Execution: 1544
|2nd Execution: 109
|3rd Execution: 105
UPDATE: Измененный запрос на основе @ ответ Клингера :
result = db.MemberWorkEntity.Where(mw => mw.WorkEntity.workEntityLevelID == 2 && mw.Member.C_deleted == null)
.Select(s => new MemberDTO
{
memberNumber = mw.Member.memberNumber,
name = mw.Member.name,
status = mw.Member.Status.name,
email = mw.Member.email,
phone = mw.Member.phone,
mobile = mw.Member.mobile,
fax = mw.Member.fax,
workEntity = mw.WorkEntity.name,
category = mw.Member.Category.name,
discountMethod = mw.Member.DiscountMethod.name,
@delegate = [email protected] ? "Yes" : "No",
leader = mw.Member.leader ? "Yes" : "No"
}).ToList();
30000 записей время исполнения (мс):
|1st Execution: 1427
|2nd Execution: 80
|3rd Execution: 76
Вы включаете подзапрос с соединением внутри проекции, естественно, он будет медленнее – Tuco
У вас нет прямой навигации между Member.MemberWorkEntity и WorkEntity? (можете ли вы добавить его?), вы должны избегать запуска этого запроса соединения внутри select, потому что он будет работать в цикле для каждого выбранного элемента. –
@Tuco, естественно, он становится медленнее, мой вопрос в том, какие изменения я могу внести в мой запрос, чтобы он был быстрее. – Ricky