Использовать внешнее соединение или заключить второй контекстный вызов в предложение where? - PullRequest
0 голосов
/ 25 января 2020

Я сформулировал два запроса, которые возвращают один и тот же результат. Наборы данных для запросов в дикой природе будут большими. Внешний запрос соединения более многословен в C#, но я уверен, что он более производительный, чем второй вариант, который оборачивает контекстный вызов предикатом в предложении where; Я прав в своем предположении?

Внешнее соединение:

var queryOuter = Context.Foo
            .GroupJoin(Context.Bar, foo => foo.Id, bar => bar.fooId,
            (foo, bar) => new
            {
                Foo = foo,
                Bar = bar
            })
            .SelectMany(fb => fb.Bar.DefaultIfEmpty(), 
            (fb, bar) => new
            {
                Foo = sr.Foo,
                Bar = bar
            })
            .Where(fb => fb.Bar == null)
            .Select(fb => fb.Foo)
            .Where(myPredicate);

В сравнении:

var query = Context.Foo.Where(foo => !Context.Bar.Any(bar => bar.fooId == foo.Id))
            .Where(myPredicate);

1 Ответ

0 голосов
/ 25 января 2020

Используя Linqpad, как предложено, и подключаясь к моей базе данных разработчика (после добавления значительного количества фиктивных данных) - я ответил на этот вопрос со следующими выводами:

Использование внешнего соединения привело к следующему SQL:

SELECT [t0].*
FROM [Foo] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[FooId]
FROM [Bar] AS [t1]) 
AS [t2] ON [t0].[Id] = [t2].[FooId]
WHERE (NOT ([t0].[SomeBool] = 1)) 
AND ([t0].[SomeDate] IS NOT NULL) 
AND (NOT ([t0].[SomeOtherDate] IS NOT NULL)) 
AND ([t2].[test] IS NULL)

Использование контекстного вызова с предикатом в условии, где предложение генерирует следующее SQL:

SELECT [t0].*
FROM [Foo] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [Bar] AS [t1]
WHERE [t1].[FooId] = [t0].[Id]))) 
AND (NOT ([t0].[SomeBool] = 1)) 
AND ([t0].[SomeDate] IS NOT NULL) 
AND ([t0].[SomeOtherDate] IS NULL)
  • Время выполнения внешнего соединения: 0,681 с
  • Предикат в таблице (контекст): 1,068 с

Я не могу с уверенностью объяснить, почему, но, как я подозревал, запрос, использующий внешнее соединение, значительно быстрее (157%). Я предполагаю, что он выполняет два действующих запроса вместо одного; один на Foo, а затем выполняет запрос на Bar в предложении where, тогда как внешнее соединение выполняет один запрос на предопределенные параметры.

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