2014-02-21 4 views
4

У меня очень странная проблема с Entity Framework и Linq. Мой первый запрос выглядит так:LINQ аналогичные запросы совершенно разные сроки исполнения

from account in context.account 
    join access in context.access on account.Id equals access.IdAccount 
    join group in context.group on access.IdGroup equals group.Id 
    where account.IdUser == idUser 
    && access.Date > DateTime(2014,02,21) 
    && group.Access > 0 
    select access 

Выполняется без проблем. Но тот же вопрос после добавления дополнительного условия (access.Status> 0) выполняется очень долго. Через 30 секунд он все еще работает:

from account in context.account 
    join access in context.access on account.Id equals access.IdAccount 
    join group in context.group on access.IdGroup equals group.Id 
    where account.IdUser == idUser 
    && access.Status > 0 
    && access.Date > DateTime(2014,02,21) 
    && group.Access > 0 
    select access 

Столбец состояния не является вычисленным столбцом. SQL-запросы, возвращаемые с

((System.Data.Objects.ObjectQuery)result).ToTraceString(); 

абсолютно разные. Где может возникнуть проблема с этим дополнительным доступом. Состояние состояния в запросе?

Сгенерированные SQL-запросы. Название столбцов отличается, потому что в примерах LINQ они переводится с польского на английский. Для первого является:

SELECT 
    `Filter1`.`IdDostep`, 
    `Filter1`.`IDKONTO1` AS `IdKonto`, 
    `Filter1`.`IndeksOms`, 
    `Filter1`.`IdGrupa`, 
    `Filter1`.`DataUtw`, 
    `Filter1`.`DataMod`, 
    `Filter1`.`DataOd`, 
    `Filter1`.`DataDo`, 
    `Filter1`.`Znacznik`, 
    `Filter1`.`Kalendarz`, 
    `Filter1`.`Komplet`, 
    `Filter1`.`Access` 
    FROM (SELECT 
    `Extent1`.`IdKonto`, 
    `Extent1`.`IdAbonenta`, 
    `Extent1`.`NrAbonenta`, 
    `Extent1`.`NrFaktury`, 
    `Extent1`.`DataFaktury`, 
    `Extent1`.`Login`, 
    `Extent1`.`Password`, 
    `Extent1`.`Notatka`, 
    `Extent1`.`IPAdres`, 
    `Extent1`.`Email`, 
    `Extent1`.`LastLogin`, 
    `Extent1`.`LastIP`, 
    `Extent1`.`Session`, 
    `Extent1`.`Regulamin`, 
    `Extent1`.`RegulaminDataAkceptacji`, 
    `Extent1`.`Powiadomienie`, 
    `Extent1`.`Gratis`, 
    `Extent1`.`PrzyEmail`, 
    `Extent1`.`PrzyIdPytanie`, 
    `Extent1`.`PrzyOdpowiedz`, 
    `Extent1`.`PrzyStatus`, 
    `Extent1`.`PrzySesja`, 
    `Extent1`.`IdKod`, 
    `Extent1`.`szerokosc`, 
    `Extent1`.`wysokosc`, 
    `Extent1`.`serwis`, 
    `Extent1`.`Nzam`, 
    `Extent1`.`parent`, 
    `Extent1`.`RegulaminLogowanie`, 
    `Extent1`.`NoBaners`, 
    `Extent1`.`KontoPromocyjne`, 
    `Extent2`.`IdDostep`, 
    `Extent2`.`IdKonto` AS `IDKONTO1`, 
    `Extent2`.`IndeksOms`, 
    `Extent2`.`IdGrupa`, 
    `Extent2`.`DataUtw`, 
    `Extent2`.`DataMod`, 
    `Extent2`.`DataOd`, 
    `Extent2`.`DataDo`, 
    `Extent2`.`Znacznik`, 
    `Extent2`.`Kalendarz`, 
    `Extent2`.`Komplet`, 
    `Extent2`.`Access` 
    FROM `konto` AS `Extent1` INNER JOIN `dostep` AS `Extent2` ON `Extent1`.`IdKonto` = `Extent2`.`IdKonto` 
    WHERE `Extent2`.`DataDo` > @gp1) AS `Filter1` INNER JOIN `grupa` AS `Extent3` ON `Filter1`.`IdGrupa` = `Extent3`.`IdGrupa` 
    WHERE (`Filter1`.`NrAbonenta` = @p__linq__0) AND (`Extent3`.`Access` > 0) 

Для второй является:

SELECT 
    `Filter1`.`IdDostep`, 
    `Filter1`.`IDKONTO1` AS `IdKonto`, 
    `Filter1`.`IndeksOms`, 
    `Filter1`.`IdGrupa`, 
    `Filter1`.`DataUtw`, 
    `Filter1`.`DataMod`, 
    `Filter1`.`DataOd`, 
    `Filter1`.`DataDo`, 
    `Filter1`.`Znacznik`, 
    `Filter1`.`Kalendarz`, 
    `Filter1`.`Komplet`, 
    `Filter1`.`Access` 
    FROM (SELECT 
    `Extent1`.`IdKonto`, 
    `Extent1`.`IdAbonenta`, 
    `Extent1`.`NrAbonenta`, 
    `Extent1`.`NrFaktury`, 
    `Extent1`.`DataFaktury`, 
    `Extent1`.`Login`, 
    `Extent1`.`Password`, 
    `Extent1`.`Notatka`, 
    `Extent1`.`IPAdres`, 
    `Extent1`.`Email`, 
    `Extent1`.`LastLogin`, 
    `Extent1`.`LastIP`, 
    `Extent1`.`Session`, 
    `Extent1`.`Regulamin`, 
    `Extent1`.`RegulaminDataAkceptacji`, 
    `Extent1`.`Powiadomienie`, 
    `Extent1`.`Gratis`, 
    `Extent1`.`PrzyEmail`, 
    `Extent1`.`PrzyIdPytanie`, 
    `Extent1`.`PrzyOdpowiedz`, 
    `Extent1`.`PrzyStatus`, 
    `Extent1`.`PrzySesja`, 
    `Extent1`.`IdKod`, 
    `Extent1`.`szerokosc`, 
    `Extent1`.`wysokosc`, 
    `Extent1`.`serwis`, 
    `Extent1`.`Nzam`, 
    `Extent1`.`parent`, 
    `Extent1`.`RegulaminLogowanie`, 
    `Extent1`.`NoBaners`, 
    `Extent1`.`KontoPromocyjne`, 
    `Extent2`.`IdDostep`, 
    `Extent2`.`IdKonto` AS `IDKONTO1`, 
    `Extent2`.`IndeksOms`, 
    `Extent2`.`IdGrupa`, 
    `Extent2`.`DataUtw`, 
    `Extent2`.`DataMod`, 
    `Extent2`.`DataOd`, 
    `Extent2`.`DataDo`, 
    `Extent2`.`Znacznik`, 
    `Extent2`.`Kalendarz`, 
    `Extent2`.`Komplet`, 
    `Extent2`.`Access` 
    FROM `konto` AS `Extent1` INNER JOIN `dostep` AS `Extent2` ON `Extent1`.`IdKonto` = `Extent2`.`IdKonto` 
    WHERE ((`Extent2`.`Komplet`) > 0) AND (`Extent2`.`DataDo` > @gp1)) AS `Filter1` INNER JOIN `grupa` AS `Extent3` ON `Filter1`.`IdGrupa` = `Extent3`.`IdGrupa` 
    WHERE (`Filter1`.`NrAbonenta` = @p__linq__0) AND (`Extent3`.`Access` > 0)  
+2

Вы можете добавить результаты 'ToTraceString()'? –

+0

Вы сравнили sql, который генерируется запросами? –

+0

индексируется 'access.Status'? – Alex

ответ

4

Проблема не должно быть в LINQ, но подстилающей выполнения оператора SQL в базе данных. Вероятно, первый запрос выполняется с использованием только индексов, а второй - для проверки таблицы.

Рекомендации по решению проблемы см. В плане выполнения обоих запросов с использованием ToTraceString() и понимания вашей проблемы. Если вам нужна дополнительная помощь, опубликуйте этот запрос, и мы дадим вам руку.

EDIT:

Как вы можете видеть из SQL запросов, они не настолько различны, они отличаются только во внутреннем фильтре запроса:

Первый запрос имеет это:

WHERE Extent2.datado > @gp1) AS Filter1 

второй:

WHERE ((Extent2.komplet) > 0) 
      AND (Extent2.datado > @gp1)) AS Filter1 

Итак, несмотря на то, что у вас есть все индексы, это не значит, что они хорошие индексы. Если у вас есть индекс для каждого из столбцов, то SQL может выбрать только один из них. Вероятно, вам нужно будет их просмотреть. Итак, как я уже говорил ранее, проверьте план выполнения запроса каждого и посмотрите, где ваше узкое место.

+0

Как вы можете видеть в запросах sql, которые я добавил раньше, запросы совершенно разные, в то время как я добавил только одно условие столбца. Почему эти запросы настолько разные? – torpederos

+0

@torpederos Вы уверены, что разместили правильный SQL-запрос linq выше? Поскольку linq имеет два «динамических» фильтра, 'Date' и' IdUser', только один фактически передается. Пожалуйста, повторите проверку, если ваша переменная 'result' является выражением linq – saamorim

+0

Вы правы, я обновил SQL-запросы. – torpederos

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