我很好奇LINQ(而不是LINQ to SQL)的表现是如何在Sql Server执行连接的情况下加入幕后的.
Sql Server在执行查询之前,生成执行计划.执行计划基本上是一个表达式树,它认为它是执行查询的最佳方式.每个节点都提供有关是否执行排序,扫描,选择,加入等信息.
在我们的执行计划中的"加入"节点上,我们可以看到三种可能的算法; 散列连接,合并连接和嵌套循环连接.Sql Server将根据Inner表和外表中的预期行数,我们正在做什么类型的连接(某些算法不支持所有类型的连接),是否需要数据排序,以及为每个Join操作选择哪种算法,以及可能还有很多其他因素
加入算法:
嵌套循环连接:最适合小输入,可以使用有序内部表进行优化.
合并连接:最适合中到大输入排序输入,或需要订购的输出.
散列连接:最适合中到大输入,可以并行化以线性扩展.
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};
Run Code Online (Sandbox Code Playgroud)
SQL查询:
SELECT *
FROM firstTable fT
INNER JOIN secondTable sT ON fT.Property = sT.Property
Run Code Online (Sandbox Code Playgroud)
如果Sql Server知道每个表中有少量行,则可以使用嵌套循环连接,如果知道其中一个表有索引,则使用合并连接;如果知道任何一个表上有很多行,则使用散列连接表,既没有索引.
Linq是否选择其连接算法?还是总是使用一个?
方法System.Linq.Enumerable按照发布的顺序执行.没有查询优化器在起作用.
有许多方法很懒惰,它允许你不能完全通过将枚举源.First或.Any或.Take在查询结束.这是最简单的优化.
对于System.Linq.Enumerable.Join,具体来说,文档声明这是一个散列连接.
默认的相等比较器Default用于散列和比较密钥.
所以例子:
//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
Run Code Online (Sandbox Code Playgroud)
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 Objects 有点不同 - 它(几乎?)总是执行 SQL Server 术语中的“散列连接”。这是因为它缺乏执行合并连接所需的索引,并且哈希连接通常比嵌套循环更有效,除非元素数量非常少。但是确定 an 中的元素数量IEnumerable<T>可能需要首先进行完整迭代,因此在大多数情况下,假设最坏情况并使用哈希算法会更快。
| 归档时间: |
|
| 查看次数: |
4887 次 |
| 最近记录: |