Как сократить время компиляции запроса Entity Framework 4? - PullRequest
7 голосов
/ 29 апреля 2010

Итог: у нас проблемы со временем компиляции запросов EF4 более 12 секунд. Кэшированные запросы только покажут нас; Есть ли способы, которыми мы можем реально сократить время компиляции? Что-то, что мы можем делать неправильно, мы можем искать? Спасибо!

У нас есть модель EF4, которая предоставляется сервисам WCF. Для каждого из наших типов сущностей мы предоставляем метод для извлечения и возврата всей сущности для отображения / редактирования, включая количество ссылочных дочерних объектов.

Для одной конкретной сущности мы должны .Include () 31 таблица / подтаблица, чтобы вернуть все соответствующие данные. К сожалению, из-за этого сборка EF-запросов запредельно замедляется: на компиляцию уходит 12-15 секунд, и создается запрос размером 30000 строк размером 7800 строк. Это серверная часть веб-интерфейса, которая должна быть более быстрой, чем эта.

Есть ли что-нибудь, что мы можем сделать, чтобы улучшить это? Мы можем скомпилировать Query.Compile - это не выполняет никакой работы до первого использования и поэтому помогает во втором и последующих выполнениях, но наш клиент нервничает, что первое использование не должно быть медленным. Аналогичным образом, если пул приложений IIS, на котором размещается веб-служба, будет переработан, мы потеряем кэшированный план, хотя мы можем увеличить срок службы, чтобы минимизировать это. Также я не вижу способа предварительно скомпилировать это заранее и / или сериализовать скомпилированный кэш запросов EF (если не считать трюков с отражением). Объект CompiledQuery содержит только GUID-ссылку в кеш, так что это кеш, который нас действительно волнует. (Записав это, мне пришло в голову, что я могу запустить что-то в фоновом режиме из app_startup, чтобы выполнить все запросы для их компиляции - это безопасно?)

Однако даже если мы решим эту проблему, мы будем динамически наращивать наши поисковые запросы с помощью предложений LINQ-to-Entities, основанных на параметрах, по которым мы ищем: я не думаю, что генератор SQL выполняет достаточно хорошую работу, мы можем переместить всю эту логику на уровень SQL, поэтому я не думаю, что мы можем предварительно скомпилировать наши поисковые запросы. Это менее серьезно, потому что в результатах поиска используется меньше таблиц, поэтому компиляция занимает всего 3-4 секунды, а не 12-15, но клиент думает, что это по-прежнему неприемлемо для конечных пользователей.

Так что нам действительно нужно как-то сократить время компиляции запроса. Есть идеи?

  • Профилирование указывает на ELinqQueryState.GetExecutionPlan в качестве места для начала, и я попытался сделать это, но без реального источника .NET 4 я не смог бы уйти очень далеко, и источник, созданный Reflector, не позволит мне войти в некоторые функции или установить в них контрольные точки.
  • Проект был обновлён с .NET 3.5, поэтому я попытался восстановить EDMX с нуля в EF4 на случай, если с ним что-то не так, но это не помогло.
  • Я пробовал объявленную здесь утилиту EFProf, но, похоже, это не поможет. Мой большой запрос приводит к сбою сборщика данных.
  • Я выполнил сгенерированный запрос с помощью настройки производительности SQL, и он уже использует индекс на 100%. Я не вижу ничего плохого в базе данных, которое могло бы вызвать проблемы с генератором запросов.
  • Есть ли что-то O (n ^ 2) в компиляторе плана выполнения - разбивает это на блоки отдельных загрузок данных, а не на все 32 таблицы одновременно, которые могут помочь? Установка EF на lazy-load не помогла.
  • Я купил предварительную версию книги О'Рейли Джули Лерман EF4, но я не могу найти там ничего, что могло бы помочь, кроме как «скомпилировать ваши запросы».

Я не понимаю, почему требуется 12-15 секунд, чтобы сгенерировать один выбор из 32 таблиц, так что я полон оптимизма, есть некоторые возможности для улучшения!

Спасибо за любые предложения! Мы работаем с SQL Server 2008 в случае, если это имеет значение, и с XP / 7 / server 2008 R2 с использованием RTM VS2010.

Ответы [ 5 ]

7 голосов
/ 29 апреля 2010

Упростите ваши запросы. Шутки в сторону; Существует почти линейная связь между сложностью запроса и временем компиляции. Два простых запроса часто намного быстрее, чем один действительно сложный запрос (даже если он предварительно скомпилирован!). Если конечной целью является скорость, выберите самый быстрый вариант.

4 голосов
/ 30 апреля 2010

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

1 голос
/ 12 апреля 2011

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

Edit: После перехода на EF5 NQueries больше не поддерживает скомпилированные запросы, поскольку он переключился на DbContext. Если вы все еще хотите взглянуть, возьмите исходный код 1.03 , который по-прежнему основан на ObjectContext и поддерживает скомпилированный запросы.

1 голос
/ 30 апреля 2010

Вы можете попробовать использовать http://www.iis.net/download/ApplicationWarmup Сейчас он находится в бета-версии, но мы тоже собираемся его использовать.

1 голос
/ 29 апреля 2010

Скорее всего, это не тот ответ, который вы ищете, но для простого обходного пути, почему бы вам не запустить CompiledQuery.Compile во время инициализации веб-приложения (сделать какой-то фиктивный вызов веб-приложения) вместо первого клиент) звонок.

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