我正在尝试提高应用程序的查询性能,但我在逻辑上陷入了困境。
因此该应用程序是专有的,因此我们无法更改应用程序端代码。然而,我们已经获得了使用底层数据库的许可(令人惊讶的是)。该应用程序调用 SQL Server 数据库,因此我们当前运行的想法是创建一个与表同名的 View 并重命名基础表。当应用程序点击 View 时, View 会调用两个 SQL CLR 函数之一,这两个函数都只是调用我们组合在一起的 Web 服务。 Web 服务执行所有逻辑,并包含对外部专有 API 的 API 调用,该 API 执行一些附加逻辑,然后返回结果。
这一切都有效,但是,当扩展到大型数据集(100,000 多行)时,我们遇到了严重的性能问题。很明显的原因是我们必须使用 Web 服务一次处理一行,其中包括 API 调用,这会产生大量延迟开销。
对此的明显解决方案是找出一种方法来限制每个查询必须访问 Web 服务的次数,但这就是我陷入困境的地方。我已经阅读了一些可能处理此类场景的不同方法,但作为一个完全的数据库新手,我很难掌握在这种情况下合适的方法。
如果有任何想法/建议,我将非常感激。
最佳答案
这里可能有一些事情需要注意:
您的 SQLCLR TVF 是否将结果流式传输(即,您是否添加到一个集合,然后在最后返回该集合,或者您是否在完成时释放每一行 - 使用
yield return
或构建出一个完整的枚举器)?如果不是流式传输,那么您应该这样做,因为它允许立即使用行,而不是等待整个过程完成。由于您要将表替换为 TVF 来源的 View ,因此性能自然会下降,因为 TVF:
- 不要报告其实际行数。 T-SQL 多语句 TVF 似乎始终返回 1 行,而 SQLCLR TVF 似乎始终返回 1000 行。
- 不维护列统计信息。从表中进行选择时,SQL Server 将自动为
WHERE
中引用的列创建统计信息。和JOIN
状况。
由于这两件事,如果实际行数为 100k,查询优化器将不容易生成适当的计划。有多少
SELECT
s 等同时访问此 View ?由于 View 每次都访问相同的 URI,因此您会受到 ServicePointManager ( ServicePointManager.DefaultConnectionLimit ) 施加的并发连接限制的约束。默认限制是一个巨大的2
!这意味着,对该 URI 的所有其他请求,同时已经有 2 个事件/打开HttpWebRequest
s,将耐心排队等待。您可以通过设置.ServicePoint.ConnectionLimit
来增加此值HttpWebRequest
的属性(property)对象。基础数据多久更改一次?由于您切换到 View ,因此不接受任何参数,因此您总是返回所有内容。这为进行一些缓存打开了大门,并且有两个选项(至少):
- 在 Web 服务中缓存数据,如果未达到特定时间限制,则返回缓存的数据,否则获取新数据、缓存并返回。
- 返回使用真实的表格。创建一个 SQL Server 代理作业,每隔几分钟(如果数据不经常更改,则可能会更长):启动一个事务,删除当前数据,通过 SQLCLR TVF 重新填充,然后提交事务。这需要 SQL 代理作业的额外部分,但随后您将获得更准确的统计数据!!
有关使用 SQLCLR 的更多信息,请访问:SQLCLR Info
关于c# - SQL CLR Web 服务调用 : Limiting Overhead,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35727978/