为什么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
)。     
已邀请:
您的第一种方法(DB中的SQL查询)非常有效,因为DB知道如何执行连接。但是将它与其他方法进行比较并没有多大意义,因为它们直接在内存中工作(Linq to DataSet) 具有多个表和
Where
条件的查询实际上执行所有表的笛卡尔积,然后过滤满足条件的行。这意味着对每个行组合评估
Where
条件(n1 * n2 * n3 * n4)
Join
运算符从第一个表中获取行,然后仅获取第二个表中具有匹配键的行,然后仅获取第三个表中具有匹配键的行,依此类推。这样效率更高,因为它不需要执行许多操作     
Join
要快得多,因为该方法知道如何组合表以将结果减少到相关组合。当您使用
Where
指定关系时,它必须创建所有可能的组合,然后测试条件以查看哪些组合是相关的。
Join
方法可以设置一个哈希表,用作快速压缩两个表的索引,而
Where
方法在所有组合已经创建之后运行,因此它不能使用任何技巧来预先减少组合。     
你真正需要知道的是为这两个语句创建的sql。有几种方法可以实现,但最简单的方法是使用LinqPad。查询结果正上方有几个按钮将更改为sql。这将为您提供比其他任何东西更多的信息。 你分享的很棒的信息。     

要回复问题请先登录注册