为什么LINQ JOIN比使用WHERE链接要快得多?
我最近升级到了VS 2010,正在玩LINQ to Dataset。我有一个强大的类型化的Authorization数据集,它位于ASP.NET WebApplication的HttpCache中。
所以我想知道实际上检查用户是否有权做某事的最快方法。如果有人感兴趣的话,这是我的数据模型和其他一些信息。
我检查了3种方法:
直接数据库
LINQ查询的Where条件为“Join” - 语法
带有Join的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-version比where-syntax快得多,这使得它无用尽管作为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.Iteration:
0,0713669秒
12,7395299秒
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
)。
没有找到相关结果
已邀请:
3 个回复
肉簧咸缮
条件的查询实际上执行所有表的笛卡尔积,然后过滤满足条件的行。这意味着对每个行组合评估
条件(n1 * n2 * n3 * n4)
运算符从第一个表中获取行,然后仅获取第二个表中具有匹配键的行,然后仅获取第三个表中具有匹配键的行,依此类推。这样效率更高,因为它不需要执行许多操作
鞋扣蚊冈借
要快得多,因为该方法知道如何组合表以将结果减少到相关组合。当您使用
指定关系时,它必须创建所有可能的组合,然后测试条件以查看哪些组合是相关的。
方法可以设置一个哈希表,用作快速压缩两个表的索引,而
方法在所有组合已经创建之后运行,因此它不能使用任何技巧来预先减少组合。
砷竣阿