为啥在 CTE 中的 WHERE 子句之前执行 UDF 调用?
Posted
技术标签:
【中文标题】为啥在 CTE 中的 WHERE 子句之前执行 UDF 调用?【英文标题】:Why UDF call is being executed before the WHERE clause in a CTE?为什么在 CTE 中的 WHERE 子句之前执行 UDF 调用? 【发布时间】:2018-04-28 17:03:03 【问题描述】:我试图理解为什么带有 UDF(用户定义函数)调用的 CTE(公用表表达式)如此缓慢。
表 TABLE1 有 1000 万行。 最后一个 where 子句 (ROWN = 1) 过滤并仅返回 10 条记录。由于未知原因,MYFUNCTION 被调用了数百万次(在 WHERE 子句过滤器之前),它正在减慢查询速度。如果 MYFUNCTION 调用被删除,查询会立即运行。
如何强制 SQL 仅在应用 WHERE 子句后才运行 MYFUNCTION?
WITH MAINDATA
AS
(
SELECT
FIELD1,
FIELD2,
FIELD3,
ROW_NUMBER() OVER (PARTITION BY FIELD5 ORDER BY FIELD6) AS ROWN
FROM
TABLE1
)
SELECT
FIELD1,
dbo.MYFUNCTION(FIELD2, FIELD3) AS FUNCTIONRESULT
FROM
MAINDATA
WHERE
ROWN = 1
【问题讨论】:
可能是因为标量 UDF 的成本计算是垃圾(直到发布在 froid 上完成的工作) - 你可以将它重写为内联 TVF 吗? @MartinSmith 我不能,这是一个复杂的功能。转换为 CLR UDF,它的速度惊人地快。只是想了解SQL决定在过滤之前调用该函数的原因。 如果可能,您能否添加 UDF 定义?它可能有助于了解 Froid 是否能够内联 UDF。 【参考方案1】:您是否尝试添加顺序 cte?
WITH MAINDATA
AS
(
SELECT
FIELD1,
FIELD2,
FIELD3,
ROW_NUMBER() OVER (PARTITION BY FIELD5 ORDER BY FIELD6) AS ROWN
FROM
TABLE1
) ,
RESULTS (
SELECT
FIELD1
FROM
MAINDATA
WHERE
ROWN = 1
)
SELECT *
,dbo.MYFUNCTION(FIELD2, FIELD3) AS FUNCTIONRESULT
FROM RESULTS
【讨论】:
以上是关于为啥在 CTE 中的 WHERE 子句之前执行 UDF 调用?的主要内容,如果未能解决你的问题,请参考以下文章
SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!
为啥在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好?