链接服务器查询导致的阻塞
背景
客户反馈数据库在上午10点时出现严重阻塞,阻塞源头会话在等待OLEDB,没有见过这个等待类型,请我们协助分析。
现象
登录SQL专家云,进入趋势分析,下钻到10点钟的活动会话,看到发生了两次严重的阻塞。该会话执行了4分32秒,阻塞也持续了这么长时间,执行完后阻塞消失。
查看会话331不同时间点的活动会话,看到等待类型都是OLEDB,等待资源都是8.56(链接服务器目标实例)上的会话589。
分析
会话331对表执行UPDATE操作,阻塞其它会话对该表的写入和查询,这是正常的,也是好理解的。分析的重点是为什么执行时间这么长,而且全部都是链接服务器的等待(OLEDB)。
下载并打开执行计划,看到各表之间使用嵌套循环来关联。嵌套循环联接也称为嵌套迭代,它将一个联接输入用作外部输入表(显示为图形执行计划中的顶端输入),将另一个联接输入用作内部(底端)输入表。外部循环逐行处理外部输入表。内部循环会针对每个外部行执行,在内部输入表中搜索匹配行。因此推断链接服务器查询循环次数太多导致执行时间长。关于嵌套循环联接和其他的联接方式参考官方文档:https://docs.microsoft.com/zh-cn/sql/relational-databases/performance/joins?view=sql-server-ver16。

在链接服务器的目标端8.56中,查看会话589在不同采集时间点的活动会话,看到该会话的请求开始时间、最后请求开始时间、最后请求结束时间三个数据是变化的,执行的SQL语句是一样的,说明在循环执行同一查询语句。粗略计算执行了3000次左右,从而验证推断是正确的。

解决
修改存储过程,先把链接服务器查询返回结果保存在临时表中,然后在UPDATE语句中关联该临时表,这样只会有一次链接服务器查询,修改完后执行时间从4分30秒下降到4秒。
总结
客户反馈这个语句以前运行的很快,解释是以前的执行计划使用的是合并联接或者哈希联接,这样对链接服务器查询只有一次。随着表数据量、统计信息等指标的变化,执行计划发生了变更,认为使用嵌套循环关联更合理,但是真正执行的时候却适得其反。从根源上说还是SQL语句写法的问题,给了SQL Server多种选择。
链接服务器的查询要跨越网络,响应时间是毫秒甚至是秒级的,如果交互次数太多就会导致执行时间指数级的增加。不能把它当本地查询一样使用,使用时一定要仔细分析执行计划。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)