Entity Framework - Первый запрос медленный - PullRequest
24 голосов
/ 08 октября 2010

Как видно из названия, у меня возникла проблема с первым запросом к базе данных SQL Server с использованием Entity Framework.

Я пытался найти ответ на разных сайтах, но, похоже, на самом деле ни у кого нетРешение этой проблемы.

Я загружаю довольно много строк из базы данных, включая два отношения 0-много.

Тесты проводились в Visual Studio 2010 с использованием модели Entity Framework 4.0 игенератор POCO (нет большой разницы во времени между обычными объектами и объектами POCO).Я также использовал шаблон представлений T4 для предварительной компиляции представлений.

База данных была на SQL Server 2008.

Что я действительно хотел бы знать, так это то, почему первый запрос намного медленнее.чем любые вторичные запросы.

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

Это большой запроси мы можем получить другие запросы, которые даже больше, и понятно, что они могут быть немного медленными, но 30 секунд слишком медленные для пользователя, чтобы ждать, особенно когда наборы данных могут получить те же данные намного быстрее.

Я провел несколько временных тестов, чтобы попытаться выяснить, в чем заключается проблема, и я был немного удивлен, увидев, что это выглядит так, как будто SQL Server работает медленно в первом запросе.

Время былоследующее:

.NET-приложение для тестирования:

  • Первый запрос: 29,6 секунд
  • Второй запрос: 3,2 секунды

SQL Profiler:

  • Первый запрос: 27 секунд
  • Второй запрос: 3,2 секунды

Окно SQL Server Query

  • Первый запрос: 8 секунд
  • Второй запрос: 4 секунды

Время в приложении измерялось с классом Stopwatch.Был измерен только запрос, и для его выполнения использовалось .ToList().

Синхронизация в SQL Server Profiler относится к тем же запросам, которые были выполнены в приложении, что показывает, что приложение использует только 2,6 секунды.для заполнения данных в объектах.

Последние 27 секунд используются для выполнения запроса на SQL Server.

Глядя на дополнительный запрос, сроки одинаковы как для приложения, так и для сервера SQL, нов этот раз выполнение запроса выполняется намного быстрее.

Я могу понять, почему приложение не использует время, потому что нет новых строк, которые необходимо преобразовать в объекты, но почему запрос намного быстрее, яожидал бы нескольких секунд из-за планов выполнения, но не 24 секунд.

Просто для целей тестирования я скопировал SQL, который генерирует Entity Framework, и открыл новое окно запроса с отдельным соединением и выполнил запрос в нем..

Как видите, на первый запрос уходит 8 секунд.4 секунды за секунду.

Надеюсь, у кого-то есть предложения.

пс.Я извиняюсь за стену текста:)

Edit 19-10-2010:
Вчера я провел тест, который, кажется, подтверждает, что строки возвращаются последовательно.Это означает, что когда строка возвращается из базы данных, она сразу материализуется (если она еще не существует в контексте), тогда возвращается следующая строка и т. Д.

Вот почему кажется, что запросзанимают много времени на сервере базы данных, потому что время материализации включено в тайминги профилировщика SQL Server.

Я не верю, что это случай чтения SQL Server с жесткого диска.Медленный запрос происходит каждый раз, когда в EF появляется «первый запрос».

ex.

  1. Запустите первый запрос с EF, оператор SQL будет медленнее, чем любой вторичный запрос
  2. Удалите контекст / хранилище
  3. Создайте новый контекст
  4. Запустите тот же запрос, что и раньше (опять первый запрос медленный и оператор SQL)

Это похоже на то, что EF отправляет некоторые параметры вместе с первым запросом, который замедляет работу сервера.

Что касается компиляции запроса, насколько я помню, запрос компилируется при первом использовании, а это означает, чтовыполнение первого запроса займет еще больше времени.

Вторичные запросы будут быстрее, но скорость вторичных запросов не является проблемой.

Я также провел тест, в котором я создал скомпилированный запрос какстатический, чтобы он был скомпилирован для всех созданных контекстов.

Затем я создал контекст, выполнил запрос, уничтожил контекст и создал новый, и снова выполнил тот же запрос.

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

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

Действительно ли ответ заключается в том, что EF работает, только если вы ничего не делаете, кроме самых простых запросов, которые возвращают толькосравнительно небольшой объем данных?

Ответы [ 5 ]

13 голосов
/ 05 февраля 2013

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

По этой ссылке http://msdn.microsoft.com/en-us/library/cc853327(v=vs.100).aspx «Загрузка метаданных» требует умеренных затрат времени, но должна происходить только один раз на домен приложения.Я не нашел никакой предварительной компиляции, как трюки для загрузки метаданных.

Временное решение, которое мы реализовали, - это выполнить второстепенный запрос по контексту в отдельном потоке при запуске приложения.Это загружает метаданные, это все еще занимает много времени (18-19 секунд в нашем случае), но приложение реагирует на загрузку.Также первая фактическая загрузка не занимает столько времени.

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

7 голосов
/ 02 мая 2015

У меня была такая же проблема. И я использовал трюк, чтобы решить эту проблему. Поскольку платформа Entity занимает немного больше времени при первом обращении, а затем она кэширует часть результатов в первый раз на своем уровне (сервер SQL тоже кэширует результат отдельно). Таким образом, я получил асинхронный доступ к платформе Entity в Моем приложении. Это сработало для меня. И мое приложение стало более гладким.

На странице Global.asax

 protected void Application_Start()
    {

        Start(() =>
        {
            using (EF.DMEntities context = new EF.DMEntities())
            {
                context.DMUsers.FirstOrDefault();
            }
        });
    }
    private void Start(Action a)
    {
        a.BeginInvoke(null, null);
    } 
4 голосов
/ 08 октября 2010

Ну, много вещей могут замедлить запрос SQL Server при первом запуске. Однако большинство из них не занимают несколько секунд.

… За исключением случайного доступа к жесткому диску. При первом запуске запроса SQL Server может потребоваться прочитать страницы базы данных из хранилища на жестком диске. При следующем запуске запроса эти страницы, вероятно, будут в памяти.

Что касается Entity Framework, то при первом запуске запроса он должен быть скомпилирован в SQL. Вы можете использовать тип CompiledQuery для предварительной компиляции запросов Entity Framework, чтобы выполнить эту работу заблаговременно, прежде чем конечный пользователь будет ждать ее.

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

1 голос
/ 17 сентября 2015

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

Обратите внимание, что я использую EF 6, и решение применимо только для EF 6.

Дэвид Рот опубликовал статью , в которой рассматривается проблема.

Микаэль Элиассон очень хорошо суммировал это в своем ответе на аналогичный вопрос:

  1. Использование кэшированного хранилища моделей БД
  2. Генерация пред-скомпилированные представления
  3. Создание предварительно скомпилированной версии фреймворка с использованием n-gen, чтобы избежать джитинга
0 голосов
/ 27 февраля 2013

У нас та же проблема.Это только с первым подходом Кодекса.У нас есть около 1500 POCO (+1500 файлов отображения POCO).Просто компиляция занимает около 1-2 минут.Метод Context.table.Add () занимает около 3-4 минут, но для первого объекта.Это как плохая шутка без решения.Эти 3-4 минуты, наверное, какой-то EF "POCO трансформация".Одно ядро ​​ЦП работает на 100%, и в профилировщике SQL ничего не происходит.

Использование первого подхода к базе данных (создание файла edmx xml) для тех же 1500 таблиц работает нормально.Это быстро, как ожидалось.

Пока нигде нет решения.Может быть, EF6 решит это.

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