LINQ类似的查询完全不同的执行时间

时间:2014-02-21 11:50:01

标签: c# sql linq

我对Entity Framework和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();

完全不同。这个额外的access.Status条件在查询中可能出现问题?

生成的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)     

1 个答案:

答案 0 :(得分:4)

问题不应该在linq中,而应该是数据库中sql语句的底层执行。可能第一个查询仅使用索引执行,而第二个查询扫描表。

建议解决您的问题,查看两个查询的执行计划,使用ToTraceString()并了解您的问题。如果您需要额外的帮助,请发布该查询计划,我们会帮您解决。

修改

正如您从sql查询中看到的那样,它们没有那么不同,它们只在内部查询过滤器中有所不同:

第一个查询包含:

    WHERE  Extent2.datado > @gp1) AS Filter1 

第二个:

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

所以,即使你有所有索引并不意味着它们是好的索引。如果每个列都有一个索引,则SQL可能只选择其中一个列。可能你需要检查它们。所以,就像我之前建议的那样,检查每个查询执行计划,看看你的瓶颈在哪里。