2014-02-20 3 views
1

У меня есть следующее заявление Linq, который работает довольно медленно (я вижу 3 второй раз)Linq оператор работает очень медленно

var results = 
    from pi in ProductItems.Include("Parent") 
    join nt in PicklistDetails 
     on pi.Diameter.PicklistCode + "-" + pi.Schedule.PicklistCode 
     equals nt.PicklistCode 
    where pi.Active 
    select new 
    { 
     Active = pi.Active, 
     ID = pi.ID, 
     IsCategory = pi.IsCategory, 
     Name = pi.Name, 
     Diameter = pi.Diameter.Value1, 
     Thickness = nt.Value1, 
     ThicknessCode = pi.Diameter.PicklistCode + "-" + pi.Schedule.PicklistCode 
    };  
results.Dump(); 

Я могу написать эквивалентное заявление непосредственно в SQL и он работает гораздо быстрее. Может ли кто-нибудь сказать мне, есть ли более эффективный способ написать запрос linq?

ОБНОВЛЕНИЕ: Спасибо за все ответы, приведенные ниже, представляют собой дополнительную информацию. Сгенерированный SQL из запроса выше LinQ выходит так:

SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Active] AS [Active], 
[Extent1].[IsCategory] AS [IsCategory], 
[Extent1].[Name] AS [Name], 
[Extent7].[Value1] AS [Value1], 
[Extent2].[Value1] AS [Value11], 
[Extent7].[PicklistCode] + N'-' + [Extent8].[PicklistCode] AS [C1] 
FROM [dbo].[ProductItem] AS [Extent1] 
INNER JOIN [dbo].[PicklistDetails] AS [Extent2] ON EXISTS (SELECT 
    1 AS [C1] 
    FROM  (SELECT 1 AS X) AS [SingleRowTable1] 
    LEFT OUTER JOIN (SELECT 
     [Extent3].[ID] AS [ID], 
     [Extent3].[PicklistCode] AS [PicklistCode] 
     FROM [dbo].[PicklistDetails] AS [Extent3] 
     WHERE [Extent1].[DiameterID] = [Extent3].[ID]) AS [Project1] ON 1 = 1 
    LEFT OUTER JOIN (SELECT 
     [Extent4].[ID] AS [ID], 
     [Extent4].[PicklistCode] AS [PicklistCode] 
     FROM [dbo].[PicklistDetails] AS [Extent4] 
     WHERE [Extent1].[ScheduleID] = [Extent4].[ID]) AS [Project2] ON 1 = 1 
    LEFT OUTER JOIN (SELECT 
     [Extent5].[ID] AS [ID], 
     [Extent5].[PicklistCode] AS [PicklistCode] 
     FROM [dbo].[PicklistDetails] AS [Extent5] 
     WHERE [Extent1].[DiameterID] = [Extent5].[ID]) AS [Project3] ON 1 = 1 
    LEFT OUTER JOIN (SELECT 
     [Extent6].[ID] AS [ID], 
     [Extent6].[PicklistCode] AS [PicklistCode] 
     FROM [dbo].[PicklistDetails] AS [Extent6] 
     WHERE [Extent1].[ScheduleID] = [Extent6].[ID]) AS [Project4] ON 1 = 1 
    WHERE (([Project1].[PicklistCode] + N'-' + [Project2].[PicklistCode]) = [Extent2].[PicklistCode]) OR (([Project3].[PicklistCode] + N'-' + [Project4].[PicklistCode] IS NULL) AND ([Extent2].[PicklistCode] IS NULL)) 
) 
LEFT OUTER JOIN [dbo].[PicklistDetails] AS [Extent7] ON [Extent1].[DiameterID] = [Extent7].[ID] 
LEFT OUTER JOIN [dbo].[PicklistDetails] AS [Extent8] ON [Extent1].[ScheduleID] = [Extent8].[ID] 
WHERE [Extent1].[Active] = 1 

я могу получить тот же результат в SQL гораздо быстрее, используя этот запрос:

select pi.Active, pi.id, pi.IsCategory, pi.Name, diameter.Value1 as diameter, nt.Value1 as thickness, diameter.PicklistCode + '-' + schedule.PicklistCode as thicknesscode 
from ProductItem pi 
    inner join PicklistDetails diameter on diameter.id = pi.DiameterID 
    inner join PicklistDetails schedule on schedule.id = pi.ScheduleID 
    inner join PicklistDetails nt on nt.PicklistCode = diameter.PicklistCode + '-' + schedule.PicklistCode 
where pi.Active = 1 

Я знаю, что я могу запустить этот SQL запрос напрямую, но я хотел бы посмотреть, могу ли я получить запрос linq быстрее. Как я уже упоминал, запрос linq выполняется в течение примерно 3 секунд, а запрос sql выполняется с шагом 1 сек.

Я проверил план выполнения и две основные элементы следующим образом 41% Sort ([ProductItem] .DiameterID по возрастанию, [ProductItem] .ScheduleID по возрастанию, [PicklistDetails] .PicklistCode по возрастанию) 49% количество строк золотника (Lazy Spool) Я не совсем уверен, что это такое.

+0

Вы проверили, как выглядит сгенерированный SQL? – MarcinJuraszek

+0

Вы посмотрели на SQL, который генерирует оператор linq? Это, как правило, дает вам подсказку. 'myContext.GetGeneratedSQL (результаты);' – McAden

+0

Я предполагаю, что для этого существует сервер sql. Если это так, это соединение выглядит медленным. Иногда присоединение к тексту может быть медленным. – clhereistian

ответ

1

Linq to entities может быть очень медленным, если вы не знаете, как правильно его использовать. Вот несколько советов, которые будут действительно улучшить вашу производительность:

1.) Избегайте поместить все объекты БД в один Entity Model

2.) Отключить отслеживание изменений для объекта, если не требуется

3 .) Использование Pre-Генерирующие Просмотры сократить время отклика для первого запроса

4.) Избегайте получения всех полей, если не требуется

5.) Выберите соответствующую коллекцию для манипулирования данных

6.) Используйте Составитель запроса везде, где требуется

7.) Получить только необходимое количество записей

8.) Избегайте использование Содержит

из этого пункта 2 и 5 очень важны. После этого вы также можете рассмотреть 8, 7 и отдохнуть. Вы всегда можете проверить, что ваш запрос linq отправляет в базу данных, используя ToTraceString(). Он даст вам эквивалентный SQL-запрос, вы сможете анализировать и улучшать производительность. Вы можете обратиться ссылкой ниже для получения дополнительной информации:

[ссылка] http://www.dotnet-tricks.com/Tutorial/entityframework/J8bO140912-Tips-to-improve-Entity-Framework-Performance.html

1

Я подозреваю, что виновник здесь ваша вычислена присоединиться значением, особенно при трогании значения из двух отдельных таблиц (диаметр и графика). SQL не может хорошо использовать свои индексы с этой структурой. Проверьте план выполнения для этого соединения на основе сгенерированного SQL. В конечном счете, моим лучшим предложением было бы удалить вычисление запросов, денормализуя вычисленный код пикетинга и поместить его в таблицу productitem, но не достаточно хорошо знаете вашу модель данных, чтобы знать, имеет ли это значение.

+0

Я добавил дополнительную информацию. Я могу написать это с помощью SQL-запроса и увидеть гораздо лучшую производительность. К сожалению, я не могу денормализовать данные в этом случае. – mark

Смежные вопросы