我已经在SQL服务器中使用了CLR存储过程一段时间了,但我仍然想知道使用它们的最佳情况是什么。
MSDN提供了一些使用指南,如重字符串操作(正则表达式),或替换声明了许多表变量和游标的T-SQL。我很想知道用户使用CLR存储过程解决了哪些问题,以及示例/基准测试。
例如,我发现CLR存储过程+ SSRS是一种很好的方法,可以从SSRS和T-SQL中获取数据操作逻辑,以及更容易阅读和操作的托管代码。
答案 0 :(得分:23)
CLR可以很好地处理许多需要非规范化和/或顺序操作的问题,并且可以用来显着提高性能,而不会牺牲SQL端的可用性(很多)。您可以采用混合方法,对大型运输使用基于集合的解决方案,并切换到紧密循环的迭代模型,而不是完全依赖基于集合或迭代的操作。
SQL Server 2008中的内置hierarchyid
和地理空间(即geography
)类型是非规范化问题的很好示例。两者都包含(几乎)任意大量的数据,这些数据难以在不损害性能的情况下进行标准化 - 您需要使用递归或游标来与它们进行任何有意义的工作,或者使用鼠标的触发器和/或计划任务来维护一个非规范化表。
我用CLR类型解决的另一个问题是内联压缩。这可能听起来像是一个毫无意义的或学术性的练习,但是当你的完全标准化数据进入太字节时,大小减少80-90%就意味着很多。 SQL现在有自己的内置压缩,SQL 2005有vardecimal,这些也是很好的工具,但是在CPU负载和压缩率方面,域感知“最小化”算法的效率可以提高几倍。显然这并不适用于所有问题,但它适用于某些问题。
此网站上经常出现的另一个非常常见的问题是即时生成序列 - 例如一系列连续日期。常见的解决方案是递归CTE,静态序列表和鲜为人知的spt_values
表,但是简单的CLR UDF比其中任何一个都表现得更好,并且提供了更大的灵活性。
最后列在我的列表中:用户定义的流聚合也非常有用,特别是对于任何与统计相关的内容。有些事情你根本无法从内置的SQL聚合中组成,例如中位数,加权移动平均数等.UDAs也可以使用多个参数,这样你就可以对它们进行参数化;从技术上讲,聚合不能保证在当前版本的SQL Server中以任何特定顺序接收数据,但您可以通过提供ROW_NUMBER
作为附加参数来解决该限制,并使用它来实现几乎任何窗口函数(让聚合体吐出UDT,然后可以将其转换为表格。)
实际上非常令人沮丧的是,真正有用的SQL-CLR应用程序的例子很少;在Google上搜索,你会获得1000万个结果,每一个结果都是一些愚蠢的字符串连接或正则表达式。这些很有用,但需要花几分钟时间来了解SQL UDT和UDA,您将开始在自己的应用程序中看到它们的大量用途。当然,不要疯狂 - 仔细考虑是否在纯SQL中有更好的解决方案 - 但也不要打折它们。
答案 1 :(得分:5)
字符串操作 - 正则表达式搜索是经典的。在CLR中很容易公开,在直接的T-SQL中很难做到。
有关实施和微观基准(SQLCLR is only 47 milliseconds compared to 6.187 seconds for the T-SQL UDF
)的详细信息,请参阅this link。
答案 2 :(得分:5)
已经提到了字符串操作(正则表达式),但也提到了DateTime算法,当然还有另外一个大问题 - 调用外部Web服务。
答案 3 :(得分:3)
这是我使用CLR过程的一个例子,我觉得它很整洁:
使用CLR存储过程和SQL作业从外部Web服务更新定时数据。
我们有一个应用程序可以将它跟踪的部分数据与外部行业数据源同步。同步每周运行一次以及按需单个更新,所以我有一个现有的webservice API来访问它。事情已经由Windows服务安排,但我想为什么不能像我们的其他SQL工作一样安排他们?
我创建了一个CLR存储过程,它引用了应用程序的webservice API。然后我为@RecordID添加了一些参数来支持单一同步,并在企业管理器SQL作业中安排它。
现在,我可以使用Job运行dB同步或在其他SQL过程或触发器中使用proc来更新外部源中的数据。
将来使用应用程序webservice API可能更清晰,只需直接使用外部Web服务即可。但是现在,这实现起来非常快,并且是将功能扩展到SQL组的一种很酷的方法。
答案 4 :(得分:2)
说实话,我只看到字符串处理,包括将CSV分成行。
除非我是DBA做DBA类型的东西,否则我会考虑任何需要超出默认信任级别的东西。
来自MSDN的RegEx和RSS提要示例:Using CLR Integration in SQL Server 2005
答案 5 :(得分:1)
对于从不提供传统SQL接口的系统中提取数据或者该接口的供应商实现低于标准非常有用。
我们有一个基于旧MUMPS平台构建的核心应用程序,在Intersystems Cache数据库上运行。数据是分层的,本质上不是关系数据。主全局数组(即表)具有多个数据级别和元素,所有数据级别和元素都按帐号组合在一起。扫描甚至一列需要从磁盘加载整个全局,并且需要8个多小时。供应商确实提供了一个ODBC驱动程序和映射到全局变量,但它经常导致扫描和极慢的查询。
我构建了一个表值函数,它采用ObjectScript(Intersystem的MUMPS方言)程序,在Cache服务器上执行它并将输出行作为数据行返回。我可以通过提供在该方执行的特定程序,然后轻松地将数据导入MSSQL作为ad-hoc内联数据源,对MUMPS端的数据访问路径进行微管理(这实际上是获得高效数据访问所需的)。
我可以使用TVF驱动数据选择,或使用CROSS APPLY
在另一端进行查找,效率相当高。如果我强迫MSSQL使用并行执行计划,我甚至可以并行地在远程端运行多个查询。