SQL CLR Web 服务调用:限制开销

SQL CLR Web Service Call: Limiting Overhead

我正在尝试提高应用程序的查询性能,但逻辑上卡住了。

因此该应用程序是专有的,因此我们无法更改应用程序端代码。然而,我们已经获得了使用底层数据库的许可(足够令人惊讶)。该应用程序调用 SQL 服务器数据库,因此我们目前的想法 运行 是创建一个与 table 同名的视图并重命名底层 table。当应用程序访问视图时,视图会调用两个 SQL CLR 函数之一,这两个函数只不过是调用我们放在一起的 Web 服务。 Web 服务执行所有逻辑,并包含对外部专有 API 的 API 调用,后者执行一些额外的逻辑,然后 returns 结果。

一切正常,但是,在扩展到大型数据集(超过 100,000 行)时,我们遇到了严重的性能问题。很明显的来源是我们必须使用 Web 服务一次处理一行,其中包括 API 调用,这会产生大量延迟开销。

解决这个问题的明显方法是找出一种方法来限制每次查询必须访问 Web 服务的次数,但这就是我遇到的问题。我已经阅读了一些可能处理这种情况的不同方法,但作为一个完全的数据库新手,我很难掌握在这种情况下什么是合适的。

如果有 ideas/recommendations,我将不胜感激。

这里大概有几点要看:

  1. 您的 SQLCLR TVF 是否将结果流出(即您是添加到一个集合然后在最后 returning 该集合,还是您发布每个完成时的行 - 使用 yield return 或构建完整的枚举器)?如果不是流式传输,那么您应该这样做,因为它允许立即使用行,而不是等待整个过程完成。

  2. 由于您将 Table 替换为源自 TVF 的视图,因此您自然会遇到性能下降,因为 TVF:

    • 不要报告它们的实际行数。 T-SQL 多语句 TVF 总是出现在 return 1 行,SQLCLR TVF 总是出现在 return 1000 行。
    • 不维护列统计信息。从 Table 中选择时,SQL 服务器将自动为 WHEREJOIN 条件中引用的列创建统计信息。


    由于这两件事,如果实际行数为 100k,查询优化器将不会轻松生成适当的计划。

  3. 有多少 SELECT 等同时点击此视图?由于视图每次都访问相同的 URI,因此您受到 ServicePointManager ( ServicePointManager.DefaultConnectionLimit ) 强加的并发连接限制的约束。而且默认限制高达 2!意思是,当已经有 2 active/open HttpWebRequests 时,对该 URI 的所有额外请求都将耐心地内联等待。您可以通过设置 HttpWebRequest 对象的 .ServicePoint.ConnectionLimit 属性 来增加它。

  4. 基础数据多久更改一次?由于您切换到一个视图,它不接受任何参数,因此您总是 return 处理所有内容。这为进行一些缓存打开了大门,并且有两个选项(至少):

    1. 在 Web 服务中缓存数据,如果未达到特定时间限制,return 缓存数据,否则获取新数据,缓存它,然后 return。
    2. 回去使用真正的 Table。创建一个 SQL 服务器代理作业,每隔几分钟(如果数据不经常更改,则可能更长时间):启动事务,删除当前数据,通过 SQLCLR TVF 重新填充,并提交事务。这需要 SQL 代理工作的额外部分,但您随后将获得更准确的统计信息!

有关使用 SQLCLR 的更多信息,请访问:SQLCLR Info