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 - SintaxeEstes 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. Onde1.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)