0

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

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

钥匙 价值
第 1 行 a/b/c/d/e 1/2/3/2/1
第 2 行 a/b/c/d/e 2/0/1/2/3
第 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. 用户在使用用户定义的聚合函数时是否有机会使用批处理模式?
4

1 回答 1

2

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

这不是 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;
于 2021-05-11T09:48:29.120 回答