d-_*_*_-b 3 sql-server parallelism sql-clr
我们有一个主分析 SP,它调用 100 个其他子 SP,所有这些都对同一组数据(声明)进行操作,检查其是否存在某些业务规则和输出差异。
SP 不需要全部按顺序运行,它们可以分成多个部分,这些部分依赖于前面的部分(顺序),但在该部分内独立(并行)。
在查看了许多选项(例如 Service Broker、Agent Jobs、Batch Files、SSIS 等)后,我使用此CLR 代码来并行化各个部分,并极大地提高了性能。
但是,当我同时运行多个 (5, 10, 15) 个主 SP(每个 SP 分析不同的声明)时,性能会随着并发性的增加而逐渐下降。我猜这是因为通过 CLR 创建多个并行线程的开销。我还看到 sp_who2 中有很多 XTP_THREAD_POOL 会话空闲。
有没有人使用 CLR 在关键 OLTP 生产工作负载中并行化存储过程?
是否有任何性能优化 SQL CLR 的最佳实践?
在开销使事情变得更糟之前,是否有可以打开的并行线程数量的阈值?
如果我的系统有 20 个内核,是否意味着创建 > 20 个并行线程没有帮助?
有没有人使用 CLR 在关键 OLTP 生产工作负载中并行化存储过程?
并行化?是的。对于“关键 OLTP 生产”系统,并非如此。这并不是说你不能这样做,但你在这里进入了相当危险的领域,因为这超出了访问外部资源(通常是 Web 服务)的典型谨慎,这些资源可能不会很快返回,因此可能“劫持”一个线程,直到 SQL Server 强制该线程让步。
在开销使事情变得更糟之前,是否有可以打开的并行线程数量的阈值?
我不相信。另外,我不确定线程数本身是否是这里的首要问题。当您增加执行次数时,您是否还检查了阻塞情况?下面有更多想法..
但是,当我同时运行多个 (5, 10, 15) 个主 SP(每个 SP 分析不同的声明)时,性能会随着并发性的增加而逐渐下降。
所以,这里有一些要点需要考虑:
除了 SQLCLR,在某种程度上,您所看到的仅仅是资源管理/并发性的性质吗?当您开始增加并发性时,您会看到收益,然后在某些时候每个额外收益的数量会减少直到它变为 0,然后进一步增加并发性实际上会产生相反的效果吗?(即规模经济/规模不经济)
是的,额外的操作是在不同的行集上完成的,但每个线程仍然需要自己的连接/会话。您是否检查了连接计数sys.dm_exec_connections
?我不确定您有多少个内核,但是有一个 DMV,sys.dm_os_schedulers,它显示了可见的调度程序计数以及您在任何给定时间点可以拥有的活动查询线程数。比方说,如果您有 32 个调度程序,那么它处理 100 个线程的速度不会比 50 个快。
执行以下查询以获取详细信息,并查看上面链接的 DMV 文档,以更好地了解各个字段返回的值:
SELECT * FROM sys.dm_os_schedulers WHERE [status] = N'VISIBLE ONLINE';
Run Code Online (Sandbox Code Playgroud)
当您在进程运行时执行该查询时,各种“任务”和“工作人员”计数字段的值如何变化,尤其是当您增加 SQLCLR 存储过程的并发执行次数时?
由于您不能在多线程中使用上下文连接,因此您正在建立常规/外部连接。这意味着 SQLCLR 存储过程不需要是本地的(好吧,这取决于它在此过程中的使用方式)。可能值得探索将这个 SQLCLR 存储过程移动到不同的服务器,在那里它不会竞争线程。除了上面关于只有这么多线程可以使用的观点之外,还需要考虑到您请求的每个线程实际上都从 CPU 中占用了 2 个,对吗?.NET 中的一个线程和 SQL Server 中的一个线程。当然,看看那个代码项目页面,我没有看到任何传递连接字符串的方法,所以也许它只是连接到(local)
实例?(我现在没有时间注册只是为了查看源代码)。
在查看该代码项目页面上的使用说明时,我注意到的一件事是它似乎将属性存储在静态变量中,因为存储过程的单独执行能够在这些执行之间维护状态。虽然Parallel_Declare
proc可用于管理分离调用者,但 SQLCLR 使用共享应用程序域模型:应用程序域是按每个数据库/程序集所有者组合创建的。如果您对所有这些都使用相同的存储过程,那么它在同一个应用程序域中运行,并且所有会话都共享相同的内存,因此共享相同的静态变量。您确定使用不同 SQL 多次执行同一个存储过程不会覆盖已经启动的并发执行吗?
虽然它可能被正确编码来处理这个问题,但您可能需要考虑创建单独的数据库来保存这个程序集的副本来运行每个单独的执行集。谁知道呢,您也可以从中获得更好的线程管理。无论您是在本地还是在远程实例上运行它,这都可能是必要的。
最后,鉴于操作的有限描述,您是否考虑过在您自己的 .NET 应用程序中实现此设置?您可以编写一个控制台应用程序来处理多线程并根据需要处理工作流:异步调用的多个同步部分。这将消除您当前在 SQLCLR 中尝试执行此操作时面临的各种风险,同时确保您可以远程运行它。然后,您可以运行控制台应用程序的多个实例,每个实例处理不同的声明集,而无需担心共享内存(因为控制台应用程序的每个实例都有自己的应用程序域),也无需从 SQL Server 中删除任何线程来管理它。
归档时间: |
|
查看次数: |
3006 次 |
最近记录: |