Por que o LINQ JOIN é muito mais rápido do que vincular ao WHERE?

Atualizei recentemente para o VS 2010 e estou brincando com o LINQ to Dataset. Eu tenho um forte conjunto de dados digitado para Autorização que está no HttpCache de um ASP.NET WebApplication.

Então, eu queria saber qual é a maneira mais rápida de verificar se um usuário está autorizado a fazer alguma coisa.Aqu é o meu modelo de dados e algumas outras informações se alguém estiver interessad

Verifiquei 3 maneiras:

directbase de dadoonsulta @LINQ comOnd condições como "Join" - sintaxeonsulta @LINQ comJunte-s - Sintaxe

Estes são os resultados com 1000 chamadas em cada função:

1.Iteração:

4,2841519 seg. 115,7796925 seg. 2.024749 seg.

2.Iteração:

3,1954857 seg. 84.97047 seg. 1.5783397 seg.

3.Iteração:

2,7922143 seg. 97,8713267 seg. 1,8432163 seg.

Média

Database: 3,4239506333 seg.Where: 99,5404964 seg.Join: 1.815435 seg.

Por que a versão Join é muito mais rápida que a sintaxe where, que a torna inútil, embora como novata em LINQ pareça ser a mais legível. Ou eu perdi algo nas minhas consultas?

Aqui estão as consultas LINQ, eu pulo o banco de dados:

Ond:

Public Function hasAccessDS_Where(ByVal accessRule As String) As Boolean
    Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
    Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
                roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
                role In Authorization.dsAuth.aspnet_Roles, _
                userRole In Authorization.dsAuth.aspnet_UsersInRoles _
                Where accRule.idAccessRule = roleAccRule.fiAccessRule _
                And roleAccRule.fiRole = role.RoleId _
                And userRole.RoleId = role.RoleId _
                And userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
                Select accRule.idAccessRule
    Return query.Any
End Function

Junte-se

Public Function hasAccessDS_Join(ByVal accessRule As String) As Boolean
    Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
    Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
                Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
                On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
                Join role In Authorization.dsAuth.aspnet_Roles _
                On role.RoleId Equals roleAccRule.fiRole _
                Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
                On userRole.RoleId Equals role.RoleId _
                Where userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
                Select accRule.idAccessRule
    Return query.Any
End Function

Agradeço antecipadamente

Edita: após algumas melhorias nas duas consultas para obter valores de desempenho mais significativos, a vantagem do JOIN é muitas vezes maior do que antes:

Junte-s:

Public Overloads Shared Function hasAccessDS_Join(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
    Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
                   Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
                   On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
                   Join role In Authorization.dsAuth.aspnet_Roles _
                   On role.RoleId Equals roleAccRule.fiRole _
                   Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
                   On userRole.RoleId Equals role.RoleId _
                   Where accRule.idAccessRule = idAccessRule And userRole.UserId = userID
             Select role.RoleId
    Return query.Any
End Function

Ond:

Public Overloads Shared Function hasAccessDS_Where(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
    Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
           roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
           role In Authorization.dsAuth.aspnet_Roles, _
           userRole In Authorization.dsAuth.aspnet_UsersInRoles _
           Where accRule.idAccessRule = roleAccRule.fiAccessRule _
           And roleAccRule.fiRole = role.RoleId _
           And userRole.RoleId = role.RoleId _
           And accRule.idAccessRule = idAccessRule And userRole.UserId = userID
           Select role.RoleId
    Return query.Any
End Function
esultado para 1000 chamadas (em um computador mais rápidJoin | 2. Onde

1.Iteração:

0,0713669 seg. 12.7395299 seg.

2.Iteração:

0,0492458 seg. 12.3885925 seg.

3.Iteração:

0,0501982 seg. 13,3474216 seg.

Média

Join: 0,0569367 seg.Where: 12,8251813 seg.

Join é 225 vezes mais rápido

Conclusão evite WHERE para especificar relações e use JOIN sempre que possível (definitivamente emLINQ to DataSet eLinq-To-Objects em geral)

questionAnswers(3)

yourAnswerToTheQuestion