Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql LINQ连接-性能_Sql_Linq_Join - Fatal编程技术网

Sql LINQ连接-性能

Sql LINQ连接-性能,sql,linq,join,Sql,Linq,Join,我很好奇LINQ(不是LINQ到SQL)在幕后执行的is连接与SQL Server执行连接的方式有什么关系 Sql Server在执行查询之前,会生成执行计划。执行计划基本上是一个表达式树,它认为这是执行查询的最佳方式。每个节点都提供有关是否进行排序、扫描、选择、加入等操作的信息 在执行计划中的“连接”节点上,我们可以看到三种可能的算法;散列联接、合并联接和嵌套循环联接。Sql Server将根据内部表和外部表中的预期行数、我们正在执行的连接类型(某些算法不支持所有类型的连接)、我们是否需要数据

我很好奇LINQ(不是LINQ到SQL)在幕后执行的is连接与SQL Server执行连接的方式有什么关系

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

在执行计划中的“连接”节点上,我们可以看到三种可能的算法;散列联接、合并联接和嵌套循环联接。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 Server知道每个表中有少量行,则可能使用嵌套循环联接;如果Sql Server知道其中一个表有索引,则可能使用合并联接;如果Sql Server知道其中一个表上有许多行,且两个表都没有索引,则可能使用哈希联接


Linq是否选择其联接算法?还是总是使用一个?

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

LINQtoSQL也不允许使用连接提示(据我所知)。因此,如果要强制执行特定类型的联接,必须使用存储过程或
Execute[Command | Query]
方法。但是,除非您通过写入
内部[HASH | LOOP | MERGE]join
来指定联接类型,否则SQL Server总是选择它认为最有效的联接类型—无论查询来自何处

其他Linq查询提供程序(如EntityFramework和NHibernateLINQ)将执行与LINQtoSQL完全相同的操作。它们都不直接知道您是如何为数据库编制索引的,因此它们都不会发送连接提示


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

LINQ本身并没有选择任何类型的算法,严格来说,它只是一种用类似SQL的语法表示查询的方法,可以映射到
IEnumerable
IQueryable
上的函数调用。LINQ完全是一种语言特性,不提供功能,只是表达现有函数调用的另一种方式

IQueryable
的情况下,完全由提供者(如LINQ to SQL)选择生成结果的最佳方法


对于LINQ to对象(使用
IEnumerable
),在所有情况下都使用简单枚举(大致相当于嵌套循环)。没有深入检查(甚至不了解)基础数据类型以优化查询。

系统上的方法。Linq.Enumerable是按发布顺序执行的。没有查询优化器在起作用

许多方法都非常懒惰,这使得您无法通过将
.First
放在查询末尾来完全枚举源代码。这是最简单的优化

特别是对于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

这实际上并不完全正确-Linq to Objects
JoinIterator
使用内部
查找
,这更接近于哈希连接。尽管出于某种原因,他们声称这是+1-执行计划规则,仅仅了解它们就可以让你轻松跻身前5%的数据库程序员行列。我很感激你的赞美,但你严重高估了我的知识。
//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