Как видно из названия, у меня возникла проблема с первым запросом к базе данных SQL Server с использованием Entity Framework.
Я пробовал искать ответ на разных сайтах, но никто, похоже, не имеет решения для этого.
Я загружаю довольно много строк из базы данных, включая два отношения 0-много.
Тесты были выполнены в Visual Studio 2010 с использованием модели Entity Framework 4.0 и генератора POCO (разница между синхронизациями между обычными объектами и объектами POCO невелика). Я также использовал шаблон T4 Views для предварительной компиляции представлений.
База данных находилась на SQL Server 2008.
Мне бы очень хотелось знать, почему первый запрос намного медленнее любых вторичных запросов.
Я также хочу знать, можно ли что-то сделать, чтобы увеличить скорость первого запроса до точки, где она находится в допустимых пределах.
Это большой запрос, и мы можем получить другие запросы, которые еще больше, и понятно, что они могут быть немного медленными, но 30 секунд слишком медленны, чтобы пользователь мог ждать, особенно когда наборы данных могут получать одни и те же данные. быстрее.
Я провел несколько тестов времени, чтобы попытаться выяснить, в чем проблема, и я был немного удивлен, увидев, что похоже на то, что SQL Server медленнее первого запроса.
Сроки были следующими:
Приложение для тестирования .NET:
- Первый запрос: 29,6 секунд
- Второй запрос: 3,2 секунды
SQL Profiler:
- Первый запрос: 27 секунд
- Второй запрос: 3,2 секунды
Окно запросов SQL Server
- Первый запрос: 8 секунд
- Второй запрос: 4 секунды
Сроки в приложении измерялись с помощью класса Stopwatch
. Был запрограммирован только запрос и .ToList()
был использован для выполнения запроса.
Сроки в SQL Server Profiler предназначены для тех же запросов, которые были выполнены в приложении, которое показывает, что приложение использует только 2,6 секунды для заполнения данных в объектах.
Последние 27 секунд используются для выполнения запроса на SQL Server.
Рассматривая вторичный запрос, тайминги одинаковы для приложения и SQL-сервера, но выполнение запроса на этот раз намного быстрее.
Я могу понять, почему приложение не использует какое-либо время, потому что нет новых строк, которые нужно преобразовать в объекты, но почему запрос намного быстрее, я бы ожидал несколько секунд из-за планов выполнения, но не 24 секунды.
Просто для тестирования я скопировал SQL, который Entity Framework генерирует и открывает новое окно запроса с отдельным подключением и выполняет запрос в нем.
Как вы видите, для первого запроса требуется 8 секунд и 4 секунды для второго.
Я надеюсь, что у кого-то есть предложения.
пс. Прошу прощения за стену текста:)
Редактировать 19-10-2010:
Вчера я сделал тест, который, похоже, поддерживает, что строки возвращаются последовательным образом. Это означает, что когда строка возвращается из базы данных, она немедленно материализуется (если она еще не существует в контексте), возвращается следующая строка и т.д.
Вот почему кажется, что запрос занимает много времени на сервере базы данных, потому что время материализации включено в тайминги профилировщика SQL Server.
Я не считаю, что это случай чтения SQL Server из жесткого диска. Медленный запрос выполняется каждый раз, когда в EF есть "первый запрос".
ех.
- Запустите первый запрос с EF, оператор SQL будет медленнее, чем любой вторичный запрос
- Утилизировать контекст/репозиторий
- Создать новый контекст
- Запустите тот же запрос, что и раньше (снова первый запрос выполняется медленно, а также оператор SQL)
Это похоже на то, что EF отправляет некоторые параметры вместе с первым запросом, который замедляет работу сервера.
Что касается компиляции запросов, как я помню, запрос скомпилирован в первый раз, когда он используется, что означает, что первый запрос займет еще больше времени.
Вторичные запросы будут быстрее, но скорость по вторичным запросам не является проблемой.
Я также проверил, где я создал скомпилированный запрос как статический, чтобы он был скомпилирован для всех созданных контекстов.
Затем я создал контекст, выполнил запрос, уничтожил контекст и создал новый, и снова выполнил тот же запрос.
Разница была не такой большой, всего несколько секунд, и в первый раз, когда я запустил запрос, все еще продолжалось до тех пор, пока он не был предварительно скомпилирован.
Что касается генерации представлений, мы уже реализуем это с использованием шаблонов T4.
Действительно ли ответ, что EF работает, только если вы ничего не делаете, кроме простейших запросов, которые возвращают только относительно небольшой объем данных?