Суммарное время выполнения SQL-запроса * НАМНОГО * ниже, чем EF ExecuteStoreCommands

Поэтому я профилировал это приложение MVC и заметил, что некоторые запросы выполняются медленно, поэтому, естественно, я профилировал и свое приложение, и базу данных.

Вот эти выводы:

Сумма всех вызовов БД в соответствии с профайлером MSSQL составляет 48 мс для 29 команд SQL. Это кажется разумным.

РЕДАКТИРОВАТЬ: каждый из этих 29 вызовов сопровождается командой exec sp_reset_connection (не уверен, если уместно).

Вот странная часть, профилирование приложения говорит это:

Entity Framework's

internal virtual DbDataReader ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

потребовалось 578мс, чтобы выполнить. Или позвольте мне сломать это еще больше.

 private ObjectResult<T> GetResults(MergeOption? forMergeOption)
{
  this.QueryState.ObjectContext.AsyncMonitor.EnsureNotEntered();
  IDbExecutionStrategy executionStrategy = DbProviderServices.GetExecutionStrategy(this.QueryState.ObjectContext.Connection, this.QueryState.ObjectContext.MetadataWorkspace);
  if (executionStrategy.RetriesOnFailure && this.QueryState.EffectiveStreamingBehaviour)
    throw new InvalidOperationException(Strings.ExecutionStrategy_StreamingNotSupported((object) executionStrategy.GetType().Name));
  else
    return executionStrategy.Execute<ObjectResult<T>>((Func<ObjectResult<T>>) (() => this.QueryState.ObjectContext.ExecuteInTransaction<ObjectResult<T>>((Func<ObjectResult<T>>) (() => this.QueryState.GetExecutionPlan(forMergeOption).Execute<T>(this.QueryState.ObjectContext, this.QueryState.Parameters)), executionStrategy, false, !this.QueryState.EffectiveStreamingBehaviour)));
}

из 578мс занимает 552мс.

И если я сломаю это еще больше.

public ObjectResult<T> Execute(MergeOption mergeOption)
    {
      EntityUtil.CheckArgumentMergeOption(mergeOption);
      return this.GetResults(new MergeOption?(mergeOption));
    }

397ms

GetEnumerator занимает 155 мс, этот метод вызывает ленивый метод CreateValue и т. д.

Я остановлюсь здесь.

Эти времена выполнения измеряются Jetbrains DotTrace.

Я действительно понимаю, что наличие EF по своей сути означает "некоторые" накладные расходы. Но это кажется чрезмерным.

EF 6.1.2, SQL Server 2012 Standard

Я слишком много спрашиваю? Я неоправданен, когда ожидаю "некоторых" накладных расходов, а не 12х?

Или я просто не подхожу к этому правильному пути?

С наилучшими пожеланиями, Т.

2 ответа

Может быть, я немного опоздал, но имейте в виду, что у профилировщика тоже есть свои издержки, и это зависит от типа профилирования. Для сэмплирования он маленький, для таймлайна - немного больше, затем идет трассировка, а самый тяжелый - построчно. Таким образом, чтобы получить наиболее точное абсолютное время выполнения функции, вы должны использовать выборку.

Однако в dotTrace 6.1 есть возможность профилировать взаимодействия SQL на стороне клиента в режиме временной шкалы, включая время открытия соединения, выполнение и накладные расходы на транспортировку результатов. Таким образом, вы можете попробовать это, чтобы выяснить, где проблема.

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

Некоторые проверки, сделанные EF, снова выполняются в БД, такие как целостность данных.

context.Configuration.AutoDetectChangesEnabled = false;

Это значительно сократит время вызовов EF, но также уменьшит функциональность.

Попробуйте копать немного больше, так как в зависимости от случая изменение значений конфигурации по умолчанию может значительно изменить время для каждого вызова.

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

Другие вопросы по тегам