Почему Linq2SQL генерирует вложенный запрос вместо использования JOIN? - PullRequest
3 голосов
/ 12 марта 2012

Я пытаюсь понять, почему Linq генерирует SQL, который используется для следующего оператора:

var dlo = new DataLoadOptions();
dlo.LoadWith<TemplateNode>(x => x.TemplateElement);
db.LoadOptions = dlo;

var data = from node in db.TemplateNodes
           where node.TemplateId == someValue
           orderby node.Left
           select node;

, который генерирует следующий SQL:

SELECT [t2].[Id],
       [t2].[ParentId],
       [t2].[TemplateId],
       [t2].[ElementId],
       [t2].[Left]  AS [Left],
       [t2].[Right] AS [Right],
       [t2].[Id2],
       [t2].[Content]
FROM   (SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Left]) AS [ROW_NUMBER],
               [t0].[Id],
               [t0].[ParentId],
               [t0].[TemplateId],
               [t0].[ElementId],
               [t0].[Left],
               [t0].[Right],
               [t1].[Id]                                AS [Id2],
               [t1].[Content]
        FROM   [dbo].[TemplateNode] AS [t0]
               INNER JOIN [dbo].[TemplateElement] AS [t1]
                 ON [t1].[Id] = [t0].[ElementId]
        WHERE  [t0].[TemplateId] = 16 /* @p0 */) AS [t2]
WHERE  [t2].[ROW_NUMBER] > 1 /* @p1 */
ORDER  BY [t2].[ROW_NUMBER]

СуществуетВнешний ключ от TemplateNode.ElementId до TemplateElement.Id.

Я бы ожидал, что запрос выдаст JOIN, например:

SELECT * FROM TemplateNode
INNER JOIN TemplateElement ON TemplateNode.ElementId = TemplateElement.Id
WHERE TemplateNode.TemplateId = @TemplateId

В соответствии с предложениями в ответы на этот вопрос Я профилировалОба запроса и JOIN работают в 3 раза быстрее, чем вложенный запрос.

Я использую приложение .NET 4.0 Windows Forms для тестирования с 64-разрядной версией SQL Server 2008 с пакетом обновления 2 (SP2) для разработчиков.

Ответы [ 2 ]

1 голос
/ 13 марта 2012

Единственная причина, по которой LINQ-SQL генерирует запрос ROW_NUMBER, связана с методом Skip.Как ни странно, как кажется вышеупомянутый SQL, я думаю, что в T-SQL нет конструкции для простой подкачки, такой как MySQL Limit 10,25, поэтому вы получаете вышеуказанный SQL при использовании Skip и Take.

IПредполагается, что для подкачки используется Skip, а LINQ-SQL изменяет запрос.Если вы используете приложение, такое как LINQ-Pad, вы можете запускать различные запросы LINQ, чтобы увидеть их сгенерированный SQL.

0 голосов
/ 12 марта 2012

Ваш пример объединения не эквивалентен.Вы не можете получить ROW_NUMBER и впоследствии выбрать только строки, ГДЕ ROW_NUMBER> 1 с простым соединением.Вам нужно будет сделать дополнительный выбор или аналогичный, чтобы получить этот результат.

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