1

Я немного измерения производительности вопроса между EF запросом прогоном через веб-приложение и запуск Profiler генерируется T-SQL непосредственно в окно SQL Query.Entity Framework и SQL Server Profiler

Ниже мой EF запрос, который выполняется с помощью веб-приложений:

IEnumerable<application> _entityList = context.applications 
        .Include(context.indb_generalInfo.EntitySet.Name) 
        .Include(context.setup_budget.EntitySet.Name) 
        .Include(context.setup_committee.EntitySet.Name) 
        .Include(context.setup_fund.EntitySet.Name) 
        .Include(context.setup_appStatus.EntitySet.Name) 
        .Include(context.appSancAdvices.EntitySet.Name) 
        .Where(e => e.indb_generalInfo != null); 

       if (isIFL != null) 
        _entityList = _entityList.Where(e => e.app_isIFL == isIFL); 

       int _entityCount = _entityList.Count(); // hits the database server at this line 

Хотя трассировка выше EF Query в SQL Profiler это показывает, что потребовалось около 221'095 мса выполнить. (Таблица приложений содержит 30 000+, indb_generalInfo с 11 000+ и appSancAdvices с 30 000 + записей).

Однако, когда я копирую T-SQL из Profiler и запускаю его непосредственно из окна Query, он принимает только 4'000 мс.

Почему это так?

+0

Вы пытались выполнить один и тот же запрос несколько раз? Entity Framework все еще нуждается в генерации этого запроса, но он будет кэшироваться для будущего запроса. Кроме того, если вы делаете 'Count()', нет необходимости в интенсивной загрузке. –

+0

Да, я пробовал это раньше. Но вопрос был именно тем, что @Arnold уведомил. –

ответ

4

Яд в этом запросе это первые слова: IEnumerable<application>. Если вы замените это на var (т. Е. IQueryable), запрос будет переведен на SQL с точностью до последнего Count(). Это займет значительно меньше времени, так как количество перевозимых данных сокращается почти до нуля.

Кроме того, поскольку bobek уже упомянул, вам не нужны Include, так как вы только считаете context.applications.

Кроме того, вы всегда заметите накладные расходы на использование ORM, например, Entity Framework.

+0

Реализация EF для IQueryable использует отложенное выполнение, поэтому, как вы говорите, запрос не переводится в sql до вызова Count(). Вы также можете вызвать AsEnumerable() или ToList(), чтобы заставить перевод, и это полезно, когда вы начинаете использовать фильтры, которые не могут быть переведены в sql. Но AFAIK просто меняет объявление переменной с IEnumerable на IQueryable, не имеет значения. – Colin

+0

@Colin Будет. Использование 'IEnumerable ' имеет тот же эффект, что и вызов 'AsEnumerable' после первого оператора, что заставляет записи захватываться в памяти до того, как остальные операторы LINQ будут применены, даже если выполнение запроса отложено до тех пор, пока 'Count'. –

+1

Я протестировал это в своем коде, изменив объявление переменной от var до IEnumerable <> и удалив вызов AsEnumerable() из запроса, который сбой, если он передан в EF. И я могу подтвердить, что @Gert верен. Я исправляюсь, и сегодня я узнал что-то новое. Таким образом, комментарий в вопросе о том, что он «попадает на сервер базы данных в этой строке», неверен, и это должно быть очевидно из запроса, просматриваемого в SQL Profiler, и результатом будет результат, а не целое число – Colin

0

Это потому, что EF необходимо сначала перевести ваш код в TSQL, что также дорого. Посмотрите на эту ссылку здесь: http://peterkellner.net/2009/05/06/linq-to-sql-slow-performance-compilequery-critical/ Это позволит вам скомпилировать LINQ и помочь вам со скоростью. Кроме того, действительно ли вам нужно много таблиц для этого запроса? Может быть, вы можете подумать о том, как отфильтровать его и вытащить только то, что вам нужно?

+0

, так как ef5 теперь следует кэшировать по умолчанию –

0

EF определенно имеет стоимость с точки зрения производительности. Но он также обеспечивает гибкость использования хранимыхпрограмм для сложного TSQL. Но, на мой взгляд, это должно быть ваше последнее средство.

0

в случае, если вы заинтересованы в производительности и EF. http://msdn.microsoft.com/en-us/data/hh949853.aspx

Однако ...

EF Запрос в SQL Profiler это показывает, что она занимает около 221'095 мс выполнить.

затем ..

копии Т-SQL с Profiler и запустить его непосредственно из окна Query

Если SQL пришел не имеет значения. Q1 взял x миллисекунды. На основе данных профилировщика SQL Точный такой же запрос Q1 'меньше использует на основе профилировщика SQL. Это означает, что источник SQL не является проблемой, он подразумевает, что затрагиваются экологические проблемы.

Наиболее очевидное объяснение: SQL-сервер буферизует множество страниц данных и может намного лучше обслуживать второй идентичный запрос.