为啥交叉应用比内连接快?

Posted

技术标签:

【中文标题】为啥交叉应用比内连接快?【英文标题】:Why cross apply is faster than inner join?为什么交叉应用比内连接快? 【发布时间】:2014-03-26 01:15:01 【问题描述】:

我有以下功能:

FunctionA - returns Object ID and Detail ID
FunctionB - returns Detail ID and Detail Name

以下查询用于提取Object IDDetail IDDetail Name

SELECT FunctionA.ID
      ,FunctionA.DetailID
      ,FunctionB.DetailName
FROM FunctionA (...)
INNER JOIN FunctionB (...) 
    ON FunctionA.DetailID = FunctionB.DetailID

下面的截图显示了它的执行计划成本(需要 32 秒):

在以下查询中,我已将查询更改为使用cross apply 而不是inner join,并使FunctionB 返回Detail Name 以获取特定的Detail ID

SELECT FunctionA.ID
      ,FunctionA.DetailID
      ,FunctionB.DetailName
FROM FunctionA (...)
CROSS APPLY FunctionB (FunctionA.DetailID) 
    ON FunctionA.DetailID = FunctionB.DetailID

下面的截图显示了它的执行计划成本(需要 3 秒):

在第一种情况下,FunctionB 返回所有对 Detail IDDetail Name,通常需要很长时间。 在第二种情况下,FunctionB 的执行速度更快,因为它只为特定的Detail ID 返回Detail Name,但它会为每个Object ID 执行。

为什么第一种情况这么慢? SQL Server 是在第二种情况下为每一行执行FunctionB,还是正在缓存结果并避免执行该函数 参数一样吗?

【问题讨论】:

能否请您以 .xml 格式发布执行计划。我在这里想两件事之一。 RBAR 是由 INNER JOIN 方法强制执行的。通过交叉应用,优化器有机会在认为合适的情况下进行不同的优化。我会冒险猜测执行计划并不相同,看看我们可以确定的那些。 只是出于好奇您使用的是哪个版本的 sql server?如果您使用 sql express 那么由于线程和内存限制,限制将导致上述情况。 @ChocoSmith 我正在使用SQL-SERVER-2012 - 检查问题标签 @gotqn *** 没有 sql-server-express-2012 的标签(仅适用于其他 express 版本)所以我很好奇你是否正在运行 express,因此问题和对线程的引用和内存限制。但是由于您正在运行非快递,因此这不是您要寻找的答案:) @ChocoSmith 对不起,我没有正确理解你。 【参考方案1】:

我认为交叉应用有时会更快,因为它可以在实际连接完成之前限制要连接的行数,因此实际连接的行数较少。

在您的第二个示例中,从 FunctionB 返回的行数将少于连接整个表时的行数,因此实际连接会更快,总时间会更短。

表中有多少行数据,它们是否正确编入索引?

【讨论】:

【参考方案2】:

CROSS APPLY 旨在与基于参数返回结果的函数和表一起使用。

所以,您查询函数的事实是“CROSS APPLY”更快的原因。

【讨论】:

以上是关于为啥交叉应用比内连接快?的主要内容,如果未能解决你的问题,请参考以下文章

使用内连接,左外连接,交叉应用获取语法错误与 Where 子句

为啥 Spark 认为这是一个交叉/笛卡尔连接

为啥这个交叉连接在 Linq 中这么慢?

内连接 外连接 自连接 交叉连接

连接(交叉连接内连接外连接自连接)

内连接,外连接,交叉连接