代码之家  ›  专栏  ›  技术社区  ›  Meiscooldude

LINQ连接-性能

  •  8
  • Meiscooldude  · 技术社区  · 14 年前

    我很好奇Linq(而不是Linq to SQL)执行的具体方式是与SQL Server执行联接的方式相关的后台联接。

    SQL Server在执行查询之前,会生成执行计划。执行计划基本上是一个表达式树,它认为这是执行查询的最佳方式。每个节点都提供有关是否进行排序、扫描、选择、联接等的信息。

    在执行计划中的一个“join”节点上,我们可以看到三种可能的算法:hash join、merge join和嵌套循环join。SQL Server将根据内部和外部表中预期的行数、正在执行的联接类型(某些算法不支持所有类型的联接)、是否需要按顺序排列数据,以及可能需要许多其他因素,为每个联接操作选择要使用的算法。

    连接算法:

    嵌套循环联接: 最适合小输入,可以使用有序的内表进行优化。

    合并连接: 最适合中型到大型输入排序输入,或需要排序的输出。

    散列连接: 最适合中型到大型输入,可以线性并行缩放。

    LINQ查询:

    DataTable  firstTable, secondTable;
    
    ...
    
    var rows = from firstRow in firstTable.AsEnumerable ()
                    join secondRow in secondTable.AsEnumerable ()
                        on firstRow.Field<object> (randomObject.Property)
                        equals secondRow.Field<object> (randomObject.Property)
               select new {firstRow, secondRow};
    

    SQL查询:

    SELECT *
    FROM firstTable fT
        INNER JOIN secondTable sT ON fT.Property = sT.Property
    

    如果SQL Server知道每个表中有少量的行,则可能使用嵌套循环联接;如果知道其中一个表具有索引,则使用合并联接;如果知道其中一个表中有大量行,并且都没有索引,则使用哈希联接。

    LINQ是否选择其连接算法?还是总是用一个?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Aaronaught    14 年前

    LINQ to SQL不向服务器发送联接提示。因此,使用LINQ to SQL的联接的性能将与“直接”发送到服务器(即使用纯ADO或SQL Server Management Studio)的相同联接的性能相同,而不指定任何提示。

    Linq to SQL也没有 允许 您可以使用连接提示(据我所知)。因此,如果要强制特定类型的联接,则必须使用存储过程或 Execute[Command|Query] 方法。但是,除非通过编写 INNER [HASH|LOOP|MERGE] JOIN 然后,SQL Server总是选择它认为最有效的连接类型——不管查询来自何处。

    其他Linq查询提供程序(如Entity Framework和NHibernate Linq)将执行与Linq to SQL完全相同的操作。这些都不知道您是如何索引数据库的,因此它们都不发送连接提示。

    Linq to对象有点不同-它(几乎是?)总是用SQL Server的说法执行“hash join”。这是因为它缺少进行合并联接所必需的索引,而哈希联接是 通常 比嵌套循环更有效,除非元素数量非常少。但要确定 IEnumerable<T> 可能首先需要一个完整的迭代,所以在大多数情况下,假设最坏的情况并使用哈希算法会更快。

        2
  •  6
  •   Amy B    14 年前

    方法论 System.Linq.Enumerable 按照发布顺序执行。没有可用的查询优化器。

    许多方法都很懒惰,这使得您不能通过 .First .Any .Take 在查询结束时。这是最简单的优化。

    对于System.Linq.Enumerable.Join, the docs 声明这是哈希联接。

    默认的相等比较器默认用于哈希和比较键。

    例如:

    //hash join (n+m) Enumerable.Join
    from a in theAs
    join b in theBs on a.prop equals b.prop
    
    //nestedloop join (n*m)  Enumerable.SelectMany
    from a in theAs
    from b in theBs
    where a.prop == b.prop
    
        3
  •  1
  •   Adam Robinson    14 年前

    LINQ本身并不选择任何类型的算法,因为严格来说,LINQ只是一种用类似SQL的语法来表达查询的方法,可以映射到 IEnumerable<T> IQueryable<T> . 林克群岛 完全地 一种语言特性,不提供功能,只提供表达现有函数调用的另一种方式。

    在情况下 可查询 ,选择产生结果的最佳方法完全取决于提供程序(如Linq to SQL)。

    在Linq to对象的情况下(使用 IEnumerable<t> ,简单枚举是在所有情况下使用的(大致相当于嵌套循环)。为了优化查询,没有对底层数据类型进行深入检查(甚至不了解这些数据类型)。