.net – 为什么LINQ JOIN比连接WHERE要快得多?

我最近升级到VS 2010,并使用LINQ to Dataset。我有一个强类型的数据集的授权,在HttpCache的ASP.NET WebApplication。

所以我想知道实际上是什么是最快的方式来检查用户是否被授权做某事。 Here是我的数据模型和一些其他信息,如果有人感兴趣。

我已经检查了3种方式:

>直接数据库
> LINQ查询,其中Where条件为“Join” – 语法
>使用Join – Syntax进行LINQ查询

这些是每个功能上1000次调用的结果:

1.迭代:

> 4,2841519 sec。
> 115,7796925秒。
> 2,024749秒。

2.Iteration:

> 3,1954857秒。
> 84,97047秒。
> 1,5783397 sec。

3.Iteration:

> 2,7922143秒。
> 97,8713267秒。
> 1,8432163秒。

平均:

>数据库:3,4239506333 sec。
>其中: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.迭代:

> 0,0713669 sec。
> 12,7395299 sec。

2.Iteration:

> 0,0492458秒。
> 12,3885925秒。

3.Iteration:

> 0,0501982秒。
> 13,3474216 sec。

平均:

>加入:0,0569367秒。
>其中:12,8251813秒。

加入速度是225倍

结论:避免WHERE指定关系并尽可能使用JOIN(绝对在LINQ to DataSet)。

>您的第一种方法(DB中的SQL查询)非常有效,因为DB知道如何执行连接。但是将它与其他方法进行比较并没有什么意义,因为它们直接在内存中工作(Linq to DataSet)
>具有多个表和一个Where条件的查询实际上执行所有表的笛卡尔乘积,然后过滤满足条件的行。这意味着对于行的每个组合(n1 * n2 * n3 * n4)评估Where条件,
> Join操作符从第一个表中获取行,然后只从第二个表中获取具有匹配键的行,然后仅从第三个表中获取具有匹配键的行,依此类推。这更有效率,因为它不需要执行尽可能多的操作
http://stackoverflow.com/questions/5551264/why-is-linq-join-so-much-faster-than-linking-with-where

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:.net – 为什么LINQ JOIN比连接WHERE要快得多?