sql Server在执行查询之前,生成执行计划.执行计划基本上是一个表达式树,它认为它是执行查询的最佳方式.每个节点都提供有关是否执行排序,扫描,选择,加入等信息.
在我们的执行计划中的“加入”节点上,我们可以看到三种可能的算法;散列连接,合并连接和嵌套循环连接. sql Server将根据Inner表和外表中的预期行数,我们正在做什么类型的连接(某些算法不支持所有类型的连接),是否需要数据排序,以及可能是很多其他因素.
加入算法:
嵌套循环连接:
最适合小型输入,可通过有序内表进行优化.
哈希加入:
最适合中到大输入,可以并行化以线性扩展.
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};
SELECT * FROM firstTable fT INNER JOIN secondTable sT ON fT.Property = sT.Property
如果sql Server知道每个表中有少量行,则可以使用嵌套循环连接,如果知道其中一个表有索引,则使用合并连接,如果知道任何一个表上有很多行,则使用散列连接表,既没有索引.
Linq是否选择其连接算法?还是总是使用一个?
解决方法
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用语中执行“散列连接”.这是因为它缺少进行合并连接所需的索引,并且散列连接通常比嵌套循环更有效,除非元素的数量非常小.但是确定IEnumerable< T>中的元素数量.可能首先需要完整的迭代,因此在大多数情况下,假设最差并使用散列算法会更快.