链接服务器查询导致的阻塞

时间:2023-02-21 15:15:00

背景

客户反馈数据库在上午10点时出现严重阻塞,阻塞源头会话在等待OLEDB,没有见过这个等待类型,请我们协助分析。

现象

登录SQL专家云,进入趋势分析,下钻到10点钟的活动会话,看到发生了两次严重的阻塞。

链接服务器查询导致的阻塞

转到活动会话原始数据,看到阻塞的源头是会话331,正在执行UPDATE语句,阻塞了其它会话对表的更新和查询。

链接服务器查询导致的阻塞

该会话执行了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多种选择。

链接服务器的查询要跨越网络,响应时间是毫秒甚至是秒级的,如果交互次数太多就会导致执行时间指数级的增加。不能把它当本地查询一样使用,使用时一定要仔细分析执行计划。