【问题标题】:Optimise use of multiple user defined functions in join condition优化连接条件下多个用户定义函数的使用
【发布时间】:2019-06-30 05:45:13
【问题描述】:

在 SQL Server 2016 (v13) 中工作。

我正在两个表(tblA 和 tblB)之间执行左连接,其中连接条件包括多个用户定义的标量函数 (UDF)。 UDF 采用来自 tblA 和 tblB 的参数。我不知道是否或如何优化查询。

(简化的)查询大致如下:

   select *
     from tblA A
left join tblB B 
       on 1 = dbo.udf1(A.field1, B.anotherField1)
      and 1 = dbo.udf2(A.field2, B.anotherField2)

例如,dbo.udf1 和 dbo.udf2 类似于:

CREATE FUNCTION dbo.udf1 (@p1 VARCHAR(100), @p2 VARCHAR(100))
  RETURNS bit
AS
BEGIN
    DECLARE @result BIT;
    SELECT @result = IIF(@p1 LIKE @p2, 1, 0);
    RETURN(@result)
END

UDF 自然要复杂一些,但都写成单个 SELECT(即,两者都是 INLINE 函数)。

我无法找到一种方法将其改造成使用表值函数的形式。我假设一定有办法改进这个查询,但不确定是否有,或者如何开始。

【问题讨论】:

  • ON 中使用标量 UDF 将导致您的查询变为不可 SARGable(标量 UDF 也以缓慢着称)。考虑到您声明这不是您的 UDF 的实际逻辑,我们最好知道它是什么,并看看我们是否可以将其更改为正确的布尔逻辑。然而,就目前而言,您的查询只会与扫描两个表一样快,UDF 应用于列中的 每个 值(很可能一次 1 行,但查询计划会告诉我们其他情况;但这对这里的事情没有帮助)。
  • 优化连接中的UDF的方法是避免连接中的UDF。如果没有真正的 UDF 代码和 示例数据预期结果(基于示例数据),就不可能提供任何可行的替代方案。
  • 谢谢你们——你们的观点大大缩小了我的担忧。连同下面的答案,我有几条路线可以尝试,尽管我怀疑它们会因为你提到的原因而受到性能限制。

标签: sql sql-server tsql optimization


【解决方案1】:

我无法找到一种方法将其改造成使用表值函数的形式。

这是可能的。请注意,此逻辑需要对 A 中的所有行与 B 中的所有行进行二次比较。这必然相当慢。

所以改写如下:

SELECT ...
FROM A
CROSS JOIN B
CROSS APPLY dbo.MyPredicate(A.x, B.y) p
WHERE p.SomeValue = 1

CROSS JOIN 是二次比较。连接后,您可以使用两个表中的值来执行连接条件。

【讨论】:

  • 这不会给出与我原始帖子中的查询完全相同的结果,但在 tblA 和上面的(内部)查询之间执行左连接将是一小步。谢谢 - 这给了我一个开始试验的地方!
  • @pcbulldozer 对,我没有注意到它是左连接。您应该能够使其与外部应用一起使用。应用操作严格来说比连接操作更强大。外部应用必须是派生表,并且谓词推入该派生表中。
  • 啊,当然!谢谢 - 我根本没有立即想到外部应用。赞赏!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多