.net - 为什么 LINQ JOIN 比 WHERE 链接快得多?

标签 .net linq performance join linq-to-dataset

我最近升级到 VS 2010,并且正在使用 LINQ to Dataset。我有一个用于授权的强类型数据集,位于 ASP.NET Web 应用程序的 HttpCache 中。

所以我想知道检查用户是否有权执行某些操作的最快方法是什么。 Here是我的数据模型和一些其他信息(如果有人感兴趣)。

我检查了3种方法:

  1. 直接数据库
  2. 使用 Where 条件作为“Join”的 LINQ 查询 - 语法
  3. 使用 Join 进行 LINQ 查询 - 语法

以下是每个函数调用 1000 次的结果:

1.迭代:

  1. 4,2841519 秒
  2. 115,7796925 秒
  3. 2,024749 秒

2.迭代:

  1. 3,1954857 秒
  2. 84,97047 秒
  3. 1,5783397 秒

3.迭代:

  1. 2,7922143 秒
  2. 97,8713267 秒
  3. 1,8432163 秒

平均:

  1. 数据库:3,4239506333 秒
  2. 地点:99,5404964 秒
  3. 加入:1,815435 秒。

为什么 Join 版本比 where 语法快得多,这使得它毫无用处,尽管作为 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 次调用的结果(在速度更快的计算机上)

  1. 加入 | 2. 地点

1.迭代:

  1. 0,0713669 秒
  2. 12,7395299 秒

2.迭代:

  1. 0,0492458 秒
  2. 12,3885925 秒

3.迭代:

  1. 0,0501982 秒。
  2. 13,3474216 秒

平均:

  1. 加入:0,0569367 秒。
  2. 地点:12,8251813 秒
<小时/>

加入速度快 225 倍

结论:避免在 WHERE 中指定关系,并尽可能使用 JOIN(通常在 LINQ to DataSetLinq-To-Objects 中)。

最佳答案

  1. 您的第一种方法(数据库中的 SQL 查询)非常有效,因为数据库知道如何执行联接。但将其与其他方法进行比较并没有什么意义,因为它们直接在内存中工作(Linq to DataSet)

  2. 包含多个表和 Where 条件的查询实际上执行所有表的笛卡尔积然后过滤行即满足条件。这意味着对每个行组合 (n1 * n2 * n3 * n4) 评估 Where 条件

  3. Join 运算符从第一个表中获取行,然后仅从第二个表中获取具有匹配键的行,然后仅从第三个表中获取具有匹配键的行, 等等。这更加高效,因为它不需要执行那么多操作

关于.net - 为什么 LINQ JOIN 比 WHERE 链接快得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5551264/

相关文章:

c# - 如何在不使用循环的情况下修剪字符串数组中的每个字符串元素?

c# - 令人难以置信的奇怪文件创建时间问题

.net - 使用 Linq.Dynamic 时如何按多个字段排序?

c# - Linq to SQL 从不返回正确结果的查询中返回多个计数

javascript - 从函数返回内部变量与直接返回值之间有区别吗

c# - 是否有超过 4 个参数的 Func 对象?

c# - 在通过敲击键盘上的 Enter 触发点击事件之前,我可以使用哪个事件来触发对标签的更新?

c# - LINQ 与 yield

performance - TSDB 与 HBase : What to choose in long term?

java - 压缩会提高性能吗?