Yakın zamanda VS 2010'a yükselttim ve LINQ to Dataset ile uğraşıyorum. Bir ASP.NET WebApplication'ın HttpCache içinde olan Yetkilendirme için güçlü bir yazılmış veri kümesine sahibim.
Bu yüzden, bir kullanıcının bir şeyi yapmaya yetkili olup olmadığını kontrol etmenin en hızlı yolunun ne olduğunu bilmek istedim. İşte benim veri modelim ve ilgilenen biri varsa diğer bazı bilgiler.
3 yolu kontrol ettim:
- doğrudan veritabanı
- İle LINQ sorgusu nerede koşullar olarak "Katıl" - Sözdizimi
- Join ile LINQ sorgusu - Sözdizimi
Bunlar, her işlevde 1000 çağrı içeren sonuçlardır:
1. Yineleme:
- 4,2841519 sn.
- 115,7796925 sn.
- 2,024749 sn.
2. Yineleme:
- 3,1954857 sn.
- 84,97047 sn.
- 1,5783397 sn.
3. Yineleme:
- 2,7922143 sn.
- 97,8713267 sn.
- 1,8432163 sn.
Ortalama:
- Veritabanı: 3,4239506333 sn.
- Nerede: 99,5404964 sn.
- Birleştirme: 1,815435 sn.
Bir LINQ acemi olarak en okunaklı gibi görünse de neden Join sürümü onu kullanışsız kılan where-syntax'tan çok daha hızlı. Veya sorgularımda bir şeyi kaçırdım mı?
İşte LINQ sorguları, veritabanını atlıyorum:
Nerede :
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
Katılmak:
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
Şimdiden teşekkür ederim.
Düzenleme : Daha anlamlı performans değerleri elde etmek için her iki sorguda da bazı iyileştirmelerden sonra, JOIN'in avantajı öncekinden birçok kez daha büyüktür:
Katıl :
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
Nerede :
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 çağrı için sonuç (daha hızlı bir bilgisayarda)
- Katıl | 2. Nerede
1. Yineleme:
- 0,0713669 sn.
- 12,7395299 sn.
2. Yineleme:
- 0,0492458 sn.
- 12,3885925 sn.
3. Yineleme:
- 0,0501982 sn.
- 13,3474216 sn.
Ortalama:
- Birleştirme: 0,0569367 sn.
- Nerede: 12,8251813 sn.
Birleştirme 225 kat daha hızlıdır
Sonuç: WHERE'den ilişkileri belirtmekten kaçının ve mümkün olduğunda JOIN'i kullanın (kesinlikle LINQ to DataSet'te ve Linq-To-Objects
genel olarak).
Join
, eğer optimize edilmiş kodu baştan yazabiliyorsan neden bir optimize ediciye güveniyorsun? Ayrıca niyetlerinizi daha net hale getirir. Yani neden sql'de JOIN'i tercih etmeniz gerektiğiyle aynı nedenler .