LINQ to Entities генерирует SQL неэффективно по сравнению с LINQ to SQL, генерируемым SQL? - PullRequest
2 голосов
/ 19 ноября 2010

Мы начали переносить проект из VS2008 с хранимыми процедурами в VS2010 с Entity Framework 4 как ORM.

Теперь мне пришлось выполнить довольно сложный запрос LINQ, чтобы вытащить данные из нашей базы данных.Обычно я сначала пытаюсь выяснить запрос LINQ, используя LINQPad (отличный инструмент!).

Теперь я заметил, что SQL, созданный LINQ to Entities, ужасен по сравнению с LINQ toSQL, который выдает оператор SQL, аналогичный тому, который мы делали ранее с хранимой процедурой.В запросе L2E было так много вложенных SELECT и INNER JOINS, что мне было просто больно смотреть на него!

Мне было любопытно, я выбрал еще один довольно сложный запрос LINQ и сравнил сгенерированный SQL LINQ to Entites с LINQ.SQL генерируется SQL.Результат был аналогичным, L2E SQL был ужасен и, скорее всего, крайне неэффективен (я не тестировал его, но мне это ясно, глядя на оператор SQL)

Извините, что могуВ данный момент я не могу привести несколько примеров запросов, но если интерес достаточно высок, я могу создать фиктивную базу данных и создать запросы, аналогичные тем, которые мы используем (запутывание наших запросов и таблиц сделает запросы нечитаемыми и бессмысленными)

Итак, каков ваш опыт работы с Entity Framework?Никто не заметил ужасных операторов SQL или большинство людей просто не заботятся?Я упускаю что-то фундаментальное в L2E, что мне следует знать?

Сейчас я очень сожалею, что мы выбрали Entity Framework вместо LINQ to SQL.

Редактировать:

Итак, я сделал несколько тестов и WOW, я удивлен!Я поместил сгенерированные операторы SQL в окно запроса в SQL Server Management Studio и выполнил каждый запрос несколько раз.Вот средние результаты выполнения запроса в цикле WHILE 1, 10 и 100 раз.

1 time:
  LINQ to SQL: 440ms
  LINQ to Entities: 240ms

10 times:
  LINQ to SQL: 2900ms
  LINQ to Entities: 910ms

100 times:
  LINQ to SQL: 31600ms
  LINQ to Entities: 7000ms

Я действительно удивлен!

Моим следующим тестом было создание простой программы на C # длясоздать и выполнить инструкцию SQL.Я использовал LINQpad для удобства.Для каждого теста я использовал LINQ to SQL и поставщика данных LINQ to Entities в LINQPad.Запрос в точности один и тот же каждый раз.Тестовая программа выглядит следующим образом:

void Main()
{
    var sw = new Stopwatch();

    for(int i = 0; i < 5; i++)
    {
        sw.Start();
        for(int y = 0; y < 10; y++)
        {
            ExecuteQuery();
        }
        sw.Stop();
        Console.WriteLine(string.Format("Pass {0}: {1}", i, sw.ElapsedMilliseconds));
        sw.Reset();
    }
}
private void ExecuteQuery()
{
    //here is my 'complex' linq query
    var dummy = (from p in....).ToList();
}

На этот раз я немного разочарован, результаты таковы:

LINQ to SQL:
Run 0: 805
Run 1: 726
Run 2: 722
Run 3: 717
Run 4: 767

LINQ to Entities:
Run 0: 3031
Run 1: 3231
Run 2: 3085
Run 3: 3127
Run 4: 3148

Полагаю, разница связана с оператором SQLпоколение?Или я бенчмаркинг совершенно не так?Предложения?

Edit2: Я реализовал запрос LINQ в нашем проекте (забыл упомянуть, что проект является веб-приложением ASP.NET MVC 3 RC).Мы в основном отображаем страницу с заказной сеткой.Загрузка данных для сетки с помощью LINQ to Entities занимает около 300-400 мс!Загрузка данных с помощью LINQ to SQL занимает около 70-80 мс.На самом деле это очень похоже на мои результаты в моем тестовом приложении в LINQPad выше.

Я искал проблемы с производительностью в EF в течение последних нескольких часов и обнаружил множество проблем с начальными запросами.И действительно, начальный запрос медленнее, но всего около 200 мс, поэтому первый запрос занимает около 600 мс, а каждый последующий запрос - 300–400 мс.Я также читал о прекомпиляции представлений с EdmGen , но это не имело значения.Я нашел еще одно сообщение в блоге , в котором сравнивалась производительность LINQ to SQL с EF , и результат, похоже, был аналогичным, хотя это было для EF 3.5.Затем я нашел в блоге сообщение об EF с тяжелым наследованием , но это не относится к моему случаю.

Кроме сотни сообщений типа "первоначальный запрос идет медленно", которые я не делалне найти ничего, связанного с моей проблемой.Я имею в виду, я не возражаю против снижения производительности по сравнению с Linq для SQL, но 70мс против 300мс - огромная разница!Это влияет на взаимодействие с пользователем нашего веб-приложения.

Последнее, что я собираюсь попробовать, - это предварительно скомпилировать запрос.Если производительность не улучшается, я окончательно переключаюсь на LINQ to SQL (хотя сам генерируемый SQL действительно быстрее!)

1 Ответ

2 голосов
/ 19 ноября 2010

Вы потеряли меня, когда сказали, что на самом деле не удосужились оценить производительность.

То, что SQL выглядит плохо, не означает, что он работает ужасно (постоянно).

При использовании Entity Framework или LINQ to SQL мне действительно все равно, как выглядят сгенерированные операторы, пока мое приложение все еще соответствует моим стандартам. Только после того, как производительность снизится до приемлемого уровня, я потрудлюсь подстроить запросы, чтобы улучшить SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...