Соединение один в один Недостаточно быстро в SQL Server
У меня есть наследование TPT в моей модели EF. Где есть абстрактный тип "Мастер", от которого наследуются несколько типов, включая "Порядок". Есть 1700000 заказов, но у мастера есть еще много строк, соответствующих другим типам.
У нас был странный случай, когда выбор 50 заказов выполнялся медленнее, чем выбор тех же 50 заказов, но с некоторыми другими связанными объектами. Отследил до базы данных, где очень простой запрос
select top 50 * from SAM.Master m
join SAL.[Order] o on o.OrderMasterID = m.MasterID
order by MasterID desc
занимает больше секунды. (Да, в нашем случае, одна секунда на самом деле слишком много). Но это может быть сделано быстрее либо
- Удаление
order by
(примерно в два раза быстрее) - сортировка по возрастанию (кластеризованные индексы по возрастанию и не может быть иначе)
- добавление
option(loop join)
(очень быстро) - используя левое внешнее соединение
- Добавление
Where FormTypeID = 1
(столбец дискриминатора в главной таблице, который равен 1 для всех заказов) (в два раза быстрее)
на самом деле единственное решение, которое дало тот же результат, это 3 и 5, но 3 невозможно с помощью Entity Framework (мы не можем добавить подсказки к запросам), а 5 недостаточно быстро
Любые предложения с благодарностью.
2 ответа
Вы можете использовать руководства плана, чтобы получить желаемое поведение. См. Использование подсказок запросов в руководствах по плану для примера. В примере требуется фактический текст оператора (T-SQL, сгенерированный EF), но вы можете обойти необходимость получения оператора EF, используяsp_create_plan_guide_from_handle
,
В вашем следующем проекте избегайте использования наследования таблиц классов с базой Master
объект, который каждая сущность происходит от...
Если вы хотите форсировать подсказку запроса. Я думаю, что ваш лучший крик - это создать процедуру хранилища и использовать подсказку запроса (подробнее здесь). Или, может быть, вы можете сделать что-то вроде этого:
var items = dc.ExecuteQuery<ToSomeObject>("YourQueryWithHints").ToList();