Недавно я обновился до VS 2010, и я играю с LINQ to Dataset. У меня есть сильный типизированный набор данных для авторизации, который находится в HttpCache ASP.NET WebApplication.
Итак, я хотел знать, что на самом деле является самым быстрым способом проверить, разрешено ли пользователю что-то делать. Здесь - это мой datamodel и некоторые другие сведения, если кому-то интересно.
Я проверил 3 способа:
- прямая база данных
- Запрос LINQ с условиями Где как "Присоединиться" - Синтаксис
- Запрос LINQ с Присоединиться - Синтаксис
Это результаты с 1000 вызовами для каждой функции:
1.Iteration:
- 4,2841519 сек.
- 115,7796925 с.
- 2,024749 сек.
2.Iteration:
- 3,1954857 сек.
- 84,97047 сек.
- 1,5783397 сек.
3.Iteration:
- 2,7922143 сек.
- 97,8713267 сек.
- 1,8432163 сек.
Средний:
- База данных: 3,4239506333 сек.
- Где: 99 5404964 сек.
- Присоединиться: 1,815435 сек.
Почему Join-версия намного быстрее, чем синтаксис where, который делает его бесполезным, хотя, будучи новичком LINQ, он кажется самым разборчивым. Или я пропустил что-то в своих запросах?
Вот запросы LINQ, я пропущу базу данных:
Где:
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
Join:
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
Спасибо заранее.
Изменить: после некоторых улучшений в обоих запросах, чтобы получить более значимые значения производительности, преимущество JOIN даже во много раз больше, чем раньше:
Join
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
Где
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
Результат для 1000 вызовов (на более быстром компьютере)
- Присоединиться | 2. Где
1.Iteration:
- 0,0713669 сек.
- 12,7395299 sec.
2.Iteration:
- 0,0492458 с.
- 12,3885925 сек.
3.Iteration:
- 0,0501982 сек.
- 13,3474216 с.
Средний:
- Присоединиться: 0,0569367 сек.
- Где: 12,8251813 сек.
Соединение в 225 раз быстрее
Вывод: избегать WHERE, чтобы указать отношения и использовать JOIN по возможности (определенно в LINQ to DataSet и Linq-To-Objects
в целом).