11

我对CROSS APPLY参数化表值函数有疑问。这是简化的伪代码示例:

SELECT * 
FROM (
    SELECT lor.*
    FROM LOT_OF_ROWS_TABLE lor
    WHERE ...
) AS lor
CROSS APPLY dbo.HeavyTableValuedFunction(lor.ID) AS htvf
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
WHERE ...
  • 表上的内部选择LOT_OF_ROWS_TABLE返回许多行。
  • 连接表LOT_OF_ROWS_TABLEANOTHER_TABLE仅返回一行或几行。
  • 表值函数非常耗时,当调用很多行时,选择会持续很长时间。

我的问题:

该函数会为从返回的所有行调用,LOT_OF_ROWS_TABLE而不管在 join 时数据将受到限制的事实ANOTHER_TABLE

选择必须采用显示的格式 - 它是生成的,实际上它要困难得多。

当我尝试重写它时,它可以非常快,但它不能像这样重写:

SELECT * 
FROM (
    SELECT lor.*
    FROM LOT_OF_ROWS_TABLE lor
    WHERE ...
) AS lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
CROSS APPLY dbo.HeavyTableValuedFunction(at.ID) AS htvf
WHERE ...

我想知道:

是否有任何设置或提示或强制选择仅对最终受限行调用函数的东西?

谢谢你。

编辑:

表值函数非常复杂: http: //pastebin.com/w6azRvxR。我们正在谈论的选择是“用户配置”并生成: http: //pastebin.com/bFbanY2n

4

3 回答 3

2

您可以将此查询分为两部分,使用表变量或临时表

SELECT lor.*,at.* into #tempresult
FROM (
    SELECT lor.*
    FROM LOT_OF_ROWS_TABLE lor
    WHERE ...
) lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
WHERE ...

现在做正确的表值函数耗时的部分

SELECT  * FROM #tempresult
CROSS APPLY dbo.HeavyTableValuedFunction(#tempresult.ID) AS htvf
于 2013-04-26T12:52:58.617 回答
1

我相信这就是您正在寻找的。

计划强制方案:创建计划指南以强制从重写查询获得的计划

基本上,它描述了使用正确的连接顺序重新编写查询以获取生成的计划。然后保存该计划并强制您现有的查询(不会更改)使用您保存的计划。

我放入的 BOL 链接甚至给出了一个具体的示例,即重写查询,将连接置于不同的顺序并使用FORCE ORDER提示。然后使用sp_create_plan_guild从重写的查询中获取计划并将其用于原始查询。

于 2013-05-03T15:03:47.290 回答
0

是和否......如果没有样本数据输入和结果输出,很难解释您想要实现的目标,以比较结果。

我想知道:

是否有任何设置或提示或强制选择仅对最终受限行调用函数的东西?

所以我会直接回答你上面的问题(3年后!!),直接声明:

您需要了解 CTE 以及 CROSS APPLY 与 INNER JOIN 之间的区别以及为什么在您的情况下使用 CROSS APPLY 是必要的。您“可以”获取函数中的代码并使用 CTE 将其应用到单个 SQL 语句中。

IE:

阅读这个这个

本质上,像这样的东西......

WITH    t2o AS
        (
        SELECT  t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
        FROM    t2
        )
SELECT  t1.*, t2o.*
FROM    t1
INNER JOIN
        t2o
ON      t2o.t1_id = t1.id
        AND t2o.rn <= 3

应用您的查询以推断您想要 ONCE 的日期,并使用 CTE,然后使用 CROSS APPLY 应用您的第二个 SQL。

你没有选择。你不能在一个 SQL 中做你想做的事情。

于 2017-02-02T06:36:08.730 回答