oracle数据库菜鸟教程 sqlserver日志查看( 二 )


使用并行应注意的问题
强制使用并行
Trace flag 8649 在SQL Server中可以不触发并行而手动指定并行,注意这个标记是无官方文档记录,勿轻易使用 。使用时只需在查询最好加上query hint:Option(querytraceon 8649)即可 。
数据分布不均,预估,碎片等问题
导致CXPACKET等待以及过多无谓IO,应对方式创建临时对象,更新统计信息,整理碎片等 。
nested loop Join导致的随机IO,及nested loop join预读问题等
冷数据中使用并行nested join可能导致实例的IO稳定性受影响,面对具体场景应酌情使用 。应对方式可以关闭nested loop预读,而nested loop预读时SQL Server也会试图将随机IO转化为连续IO,如具体应用合理应接受并行nested loop join 。
线程饥饿问题(worker thread starvation)
前面我们说过,线程的授予是按照分支(branches)及并行度授予的,如果并行度高,此时复杂的查询下分支又很多,这个时候可能针对某个查询分配过多线程,加之这类查询又高并发,则这时出现线程饥饿的几率就大大增加了 。具体生产中,这个应引起我们的注意 。这里给大家举个简单的实例,感兴趣的同学可以自己测试下 。这个查询有5个分支,分支所申请的线程就是5*16共80个!如图5-1:

oracle数据库菜鸟教程 sqlserver日志查看



oracle数据库菜鸟教程 sqlserver日志查看


图5-1
并行死锁
并行执行提升查询响应时间,提高用户体验已经被我们所熟知了,但正如我一直强调的,任何事物均有利弊,我们要做的重点是权衡 。并行死锁在并行执行中也会偶尔出现,官方给出的解释是SQL Server的“BUG”,你只需将查询的MAXDOP调整为1,死锁就会自动消失,但有时我们还应追溯其本质 。这里用一个实例为大家说明下并行死锁的原因,以便我们更好的利用并行 。
生成测试数据

oracle数据库菜鸟教程 sqlserver日志查看


接下来我们执行如下语句,取30000下最大偶数,此时我将执行并行数maxdop随意调整为奇数,3,5,7我的执行都可以迅速返回结果 。

oracle数据库菜鸟教程 sqlserver日志查看


但当我将并行数调整为偶数时,执行时间居然长达数秒…打开trace profiler跟踪dead lock chain我们发现,当并行数为偶数时出现了死锁 。
注:我们用Trace profiler捕捉死锁
如图6-1,6-2,6-3:
oracle数据库菜鸟教程 sqlserver日志查看



oracle数据库菜鸟教程 sqlserver日志查看


图6-1

oracle数据库菜鸟教程 sqlserver日志查看


图6-2

oracle数据库菜鸟教程 sqlserver日志查看


图6-3
有的同学可能觉得蹊跷,发生了什么我们具体分析下并行死锁的相应执行计划 。
分析:
  • 访问基表数据时用的是聚集索引扫描,但扫描方式是backward,而SQL server中只有forward scan可以并行扫描,backward只能串行扫描
  • 因此在做exchange向各个threads分发数据时(distribute streams)采用roundrobin轮询分发数据,这势必造成奇偶数据按threads分开流向下一个过滤操作符
  • 在Filter时将奇数的数据过滤,而相应的threads也就没有了数据
  • 所以在最后exchange汇总数据时(gather streams)有的threads没有数据,因而造成死锁 。
(注:thread 0为主线程,不参与并行分支工作)
分析如图6-4:

推荐阅读