Нещодавно я перейшов до VS 2010 і граю разом з LINQ до Dataset. У мене є сильний типізований набір даних для авторизації, який знаходиться в HttpCache ASP.NET WebApplication.
Тож я хотів дізнатися, що насправді є найшвидшим способом перевірити, чи має право користувач щось робити. Ось моя модель даних та інша інформація, якщо хтось зацікавлений.
Я перевірив 3 способи:
- пряма база даних
- Запит LINQ з Де умови як "Приєднатися" - Синтаксис
- LINQ запит з реєстрації - Синтаксис
Це результати з 1000 дзвінків на кожну функцію:
1.Ітерація:
- 42841519 сек.
- 115,7796925 сек.
- 2024749 сек.
2.Ітерація:
- 31954857 с.
- 84 97047 сек.
- 1,5783397 сек.
3.Ітерація:
- 27922143 сек.
- 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
Спасибі заздалегідь.
Редагувати : після деяких вдосконалень обох запитів, щоб отримати більш значущі показники ефективності, перевага приєднання навіть у багато разів більша, ніж раніше:
Приєднуйтесь :
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 разів швидше
Висновок: уникайте, де БУДЬ вказувати відносини, і використовуйте ПРИЄДНАЙТЕ, коли це можливо (обов'язково в LINQ до DataSet і Linq-To-Objects
взагалі).
Join
anywhy, навіщо покладатися на оптимізатор, якщо ви можете написати оптимізований код з самого початку? Це також робить ваші наміри яснішими. Таким чином , по тимі ж причинам , чому ви повинні віддають перевагу JOIN в SQL .