微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在使用 SQLCLR 用户定义聚合函数 (UDA)

如何解决如何在使用 SQLCLR 用户定义聚合函数 (UDA)

我们在使用 sqlCLR 用户定义聚合函数 (UDA) 时发现了性能问题,

这是我们的场景: 我们需要计算 2 列:key 和 value,其值如下:

价值
Row_1 a/b/c/d/e 1/2/3/2/1
Row_2 a/b/c/d/e 2/0/1/2/3
Row_3 a/b/c/d/e 2/3/4/1/2

我们需要一个聚合函数获取每个指标的总和,在上面的例子中,我们想要得到这样的结果:

价值
结果 a/b/c/d/e 5/5/8/5/6

没有我们可以使用的本机聚合函数来获得这种结果,因此我们使用 sqlCLR UDA 来实现这种结果。我们发现当 sqlCLR UDA 与 GROUP BY 子句一起使用时,该 UDA 的性能很差。

经过一番调查,我们发现原因如下:

  1. 当我们使用 sqlCLR UDA 时,必须使用 StreamAggregate 操作,并且会引入昂贵的排序运算符,从而降低 UDA 的性能
  2. 当我们使用 sqlCLR UDA 时,只能使用行模式来计算排序和聚合运算符中的结果。

所以,我的问题是:

  1. 用户是否有机会在使用用户定义的聚合函数时强制 sql Server 使用哈希聚合运算符而不是流运算符?
  2. 在使用用户定义的聚合函数时,用户是否有机会使用排序运算符?
  3. 在使用用户定义的聚合函数时,用户是否有机会使用批处理模式?

解决方法

当数据库违反第一范式时,您将永远不会获得任何性能......因为这导致没有关系数据库......并且关系引擎专门设计用于快速处理关系数据而不是非关系数据。

这不是 UDA 性能的问题,而是您的设计导致严重的反性能问题。

第一范式表示表中的列必须始终具有单个(标量)值。您放置了一个违反第一范式的值列表。

只需通过添加子表重新设计数据库并将键和值放入该子表中,您就会有性能!

你可以试试这个:

CREATE TABLE T_CHILD
(ID_CHILD       INT IDENTITY PRIMARY KEY,ID_ROW         VARCHAR(32),--REFERENCES T_FATHER (ID_ROW),KEY_CHILD      VARCHAR(16),VALUE_CHILD    INT);
GO

INSERT INTO T_CHILD
SELECT ID_ROW,k.value,V_EMP.value
FROM   T_FATHER
       OUTER APPLY STRING_SPLIT([key],'/') AS k
       OUTER APPLY STRING_SPLIT([value],'/') AS v;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。