Recientemente me actualicé a VS 2010 y estoy jugando con LINQ to Dataset. Tengo un conjunto de datos de tipo fuerte para la autorización que está en HttpCache de una aplicación web ASP.NET.
Así que quería saber cuál es en realidad la forma más rápida de comprobar si un usuario está autorizado para hacer algo. Aquí está mi modelo de datos y alguna otra información si alguien está interesado.
He comprobado 3 formas:
- base de datos directa
- Consulta LINQ con condiciones Where como "Unir" - Sintaxis
- Consulta LINQ con Join - Sintaxis
Estos son los resultados con 1000 llamadas en cada función:
1.Iteración:
- 4.2841519 seg.
- 115,7796925 seg.
- 2.024749 seg.
2.Iteración:
- 3,1954857 seg.
- 84,97047 seg.
- 1,5783397 seg.
3.Iteración:
- 2,7922143 seg.
- 97,8713267 seg.
- 1,8432163 seg.
Promedio:
- Base de datos: 3,4239506333 seg.
- Donde: 99,5404964 seg.
- Unirse: 1.815435 seg.
¿Por qué la versión Join es mucho más rápida que la sintaxis where, lo que la hace inútil, aunque como novato en LINQ parece ser la más legible? ¿O me he perdido algo en mis consultas?
Aquí están las consultas LINQ, me salto la base de datos:
Donde :
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
Unirse:
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
Gracias de antemano.
Editar : después de algunas mejoras en ambas consultas para obtener valores de rendimiento más significativos, la ventaja de JOIN es incluso muchas veces mayor que antes:
Únete :
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
Donde :
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
Resultado de 1000 llamadas (en una computadora más rápida)
- Únete | 2. Donde
1.Iteración:
- 0,0713669 seg.
- 12,7395299 seg.
2.Iteración:
- 0,0492458 seg.
- 12,3885925 seg.
3.Iteración:
- 0,0501982 seg.
- 13,3474216 seg.
Promedio:
- Unirse: 0,0569367 seg.
- Donde: 12,8251813 seg.
Unirse es 225 veces más rápido
Conclusión: evite WHERE para especificar relaciones y use JOIN siempre que sea posible (definitivamente en LINQ to DataSet y Linq-To-Objects
en general).
Join
cualquier motivo, ¿por qué confiar en un optimizador si puedes escribir el código optimizado desde el principio? También aclara tus intenciones. Entonces, las mismas razones por las que debería preferir JOIN en sql .