Я недавно обновился до VS 2010 и играю с LINQ to Dataset. У меня есть строго типизированный набор данных для авторизации, который находится в HttpCache веб-приложения ASP.NET.
Поэтому я хотел знать, как на самом деле самый быстрый способ проверить, имеет ли пользователь право что-то делать. Вот моя модель данных и другая информация, если кому-то интересно.
Я проверил 3 способа:
- прямая база данных
- Запрос LINQ с условиями Where как «Присоединиться» - синтаксис
- Запрос LINQ с объединением - синтаксис
Это результаты с 1000 вызовами каждой функции:
1.Итерация:
- 4,2841519 сек.
- 115,7796925 сек.
- 2,024749 сек.
2.Итерация:
- 3,1954857 сек.
- 84,97047 сек.
- 1,5783397 сек.
3.Итерация:
- 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
Присоединиться:
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 даже во много раз больше, чем раньше:
Присоединяйтесь :
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.Итерация:
- 0,0713669 сек.
- 12,7395299 сек.
2.Итерация:
- 0,0492458 сек.
- 12,3885925 сек.
3.Итерация:
- 0,0501982 сек.
- 13,3474216 сек.
Средний:
- Присоединиться: 0,0569367 сек.
- Где: 12,8251813 сек.
Присоединяйтесь в 225 раз быстрее
Заключение: избегайте WHERE для указания отношений и по возможности используйте JOIN (обязательно в LINQ to DataSet и Linq-To-Objects
в целом).