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


    背景

    客户反馈数据库在上午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多种选择。

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

  • 相关阅读:
    vm2 组件存在沙箱逃逸漏洞
    通信原理板块——利用香农公式对连续信道的信道容量计算
    MySQL的Redo log 、Undo log、 Binlog
    Mybatis 一级缓存和二级缓存原理区别 (图文详解)
    html 边缘融合加载
    讲透金融风控建模全流程(附 Python 代码)
    快手版Sora「可灵」开放测试:生成超120s视频,更懂物理,复杂运动也能精准建模...
    多次复制Excel符合要求的数据行:Python批量实现
    flink的regular join/window join/interval join/temporal join/lookup join
    腾讯云发送短信
  • 原文地址:https://www.cnblogs.com/zhuancloud/p/17140954.html