Почему SQL, создаваемый LINQ-to-Entities, настолько неэффективен?

Следующий (урезанный) фрагмент кода представляет собой запрос Linq-To-Entities, результатом которого является SQL (через ToTraceString), который намного медленнее, чем запрос, созданный вручную. Я делаю что-то глупое, или Linq-to-Entities просто плохо оптимизирует запросы?

У меня есть ToList() в конце запроса, так как мне нужно выполнить его, прежде чем использовать его для построения структуры данных XML (что было совсем другой проблемой).

var result = (from mainEntity in entities.Main
              where (mainEntity.Date >= today) && (mainEntity.Date <= tomorrow) && (!mainEntity.IsEnabled)
              select new
              {
                  Id = mainEntity.Id,
                  Sub =
                      from subEntity in mainEntity.Sub
                      select
                      {
                          Id = subEntity.Id,
                          FirstResults =
                              from firstResultEntity in subEntity.FirstResult
                              select new
                              {
                                  Value = firstResultEntity.Value,
                              },
                          SecondResults =
                              from secondResultEntity in subEntity.SecondResult
                              select
                              {
                                  Value = secondResultEntity.Value,
                              },
                          SubSub =
                              from subSubEntity in entities.SubSub
                              where (subEntity.Id == subSubEntity.MainId) && (subEntity.Id == subSubEntity.SubId)
                              select
                                  new
                                  {
                                      Name = (from name in entities.Name
                                              where subSubEntity.NameId == name.Id
                                              select name.Name).FirstOrDefault()
                                  }
                          }
              }).ToList();

Во время работы над этим у меня также возникли серьезные проблемы с датами. Когда я просто попытался включить возвращенные даты в свою структуру данных, я получил внутреннюю ошибку «1005».


person Community    schedule 28.04.2009    source источник


Ответы (2)


Просто как общее наблюдение, не основанное на каком-либо практическом опыте работы с Linq-To-Entities (пока): наличие четырех вложенных подзапросов внутри одного запроса не выглядит ужасно эффективным и быстрым для начала.

Я думаю, что ваше очень широкое заявление о (отсутствии) качества SQL, сгенерированного Linq-to-Entities, не гарантируется, и вы также не подтверждаете его большим количеством доказательств.

Несколько уважаемых людей, включая Рико Мариани (гуру MS Performance) и Джули Лерман (автор «Programming EF») показал в различных тестах, что в целом и в целом «движки» Linq-to-SQL и Linq-to-Entities на самом деле не так уж плохи — в целом они достигают не менее 80-95% от возможной пиковой производительности. Не каждый разработчик приложений .NET может достичь этого :-)

Есть ли способ переписать этот запрос или изменить способ извлечения фрагментов, составляющих его содержимое?

Марк

person marc_s    schedule 29.04.2009
comment
Не рекомендуются ли вложенные подзапросы в LINQ-to-Entities (например, вместо объединений)? См. blogs.msdn.com/esql/archive/2007/11. /01/ - person dommer; 29.04.2009

Вы пытались не материализовать результат немедленно, вызвав .ToList()? Я не уверен, что это будет иметь значение, но вы можете увидеть улучшение производительности, если будете перебирать результат вместо вызова .ToList()...

foreach( var r in result )
{
  // build your XML
}

Кроме того, вы можете попробовать разбить один огромный запрос на отдельные запросы, а затем перебрать результаты. Отправка всего одним большим глотком может быть проблемой.

person JP Alioto    schedule 29.04.2009