Итог: у нас проблемы со временем компиляции запросов 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.