ฉันเพิ่งอัปเกรดเป็น VS 2010 และกำลังเล่นกับ LINQ เป็น Dataset ฉันมีชุดข้อมูลที่พิมพ์แน่นหนาสำหรับการอนุญาตที่อยู่ใน HttpCache ของ ASP.NET WebApplication
ฉันจึงอยากรู้ว่าอะไรคือวิธีที่เร็วที่สุดในการตรวจสอบว่าผู้ใช้ได้รับอนุญาตให้ทำบางสิ่งหรือไม่ นี่คือรูปแบบข้อมูลของฉันและข้อมูลอื่น ๆ หากมีใครสนใจ
ฉันตรวจสอบแล้ว 3 วิธี:
- ฐานข้อมูลโดยตรง
- แบบสอบถาม LINQ กับที่ไหนเงื่อนไขที่ "เข้าร่วม" - ไวยากรณ์
- แบบสอบถาม LINQ พร้อมเข้าร่วม - ไวยากรณ์
นี่คือผลลัพธ์ที่มีการโทร 1,000 ครั้งในแต่ละฟังก์ชัน:
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 จึงเร็วกว่าไวยากรณ์ที่ซึ่งทำให้ไม่มีประโยชน์แม้ว่าในฐานะมือใหม่ 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
ผลลัพธ์สำหรับการโทร 1,000 ครั้ง (บนคอมพิวเตอร์ที่เร็วกว่า)
- เข้าร่วม | 2. ที่ไหน
1. การนึ่ง:
- 0,0713669 วินาที
- 12,7395299 วินาที
2. การนึ่ง:
- 0,0492458 วินาที
- 12,3885925 วินาที
3. การนึ่ง:
- 0,0501982 วินาที
- 13,3474216 วินาที
เฉลี่ย:
- เข้าร่วม: 0,0569367 วินาที
- ที่ไหน: 12,8251813 วินาที
เข้าร่วมเร็วขึ้น 225 เท่า
สรุป:หลีกเลี่ยง WHERE เพื่อระบุความสัมพันธ์และใช้ JOIN ทุกครั้งที่ทำได้ (แน่นอนในLINQ ไปยัง DataSetและLinq-To-Objects
โดยทั่วไป)