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


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


图6-4
而反观并行采用奇数并行数,这时当分发数据时就不会造成某个thread所持有的数据只是奇数或是偶数,也就不会造成后来的情形,死锁也就不会出现 。如图6-4感兴趣的同学可以做实验调整并行数并阅读相应的执行计划 。

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


图6-5
至此我们应该可以明白了 。
万事皆有因果,一个简单的BUG可以做为回应,但深究可能窥其本质,并且很有意思 。技术人需有这种精神 。
优化实践
最后咱们再通过一个简单的实例说下优化实践 。
日常的OLTP环境中,有时会涉及到一些统计方面的SQL语句,这些语句可能消耗巨大,进而影响整体运行环境,这里我为大家介绍如何利用SQL Server中的“类MapReduce”方式,在特定的统计情形中不牺牲响应速度的情形下减少资源消耗 。
我们可能经常会利用开窗函数对巨大的数据集进行分组统计排序 。比如下面的例子:
脚本环境

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



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



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



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



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



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


当我们针对bigProduct表的productid分组,并按照bigTransactionHistory的actualcost及quantity分别排序取结果集语句如下:

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


执行此语句并输出实际执行计划如图7-1:

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


图7-1
可以看出我的这条语句由于对大量结果集进行排序,致使消耗了365MB的内存,并且由于分别对actualcost, quantity排序使得在进行第二个排序时内存不足并溢出,排序的操作只能在tempdb中进行 。
Sort由于是典型的计算密集型运算符,此查询在我的机器上执行时间为5s 。
大量的内存被个别查询长时间独占,使得Buffer Pool的稳定性下降,进而可能影响整体吞吐 。
关于SQL Server的Sort限于篇幅这里就不细说了 。
在介绍“类MapReduce”之前,我想先接着上面Sort溢出的现象给大家简单介绍下通过Query hints 来影响优化器的资源分配 。

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


通过查询可以看出由于我加了Query Hint,改变了优化器的资源评估标准,使得优化器认为productid本身需要资源从1001 and 3001分配变为了1001 and 5001分配,内存申请由365MB变为了685MB,接近一倍的增长,避免了溢出 。并且执行时间也由5S变为了2S,提升了用户体验 。
如图7-2:

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


图7-2
可以看到溢出与不溢出在查询消耗时间上差别很大,但这样就是好了吗?其实未必,毕竟即便在非溢出的情形中将近700MB的内存近2s内被这个查询占用,这在高并发的OLTP环境中是伤全局的 。那更理想的解决方式呢?
在并行执行计划中是多个线程(CPU核)协同工作,这里面的Sort面对大量数据结果集时即便多核同时进行,在复杂的预算面前也是有些力不从心 。在分布式的思想中,讲究分而治之,我们只要将大的结果集化为多个小的部分并多核同时进行排序,这样就达到了分而治之的效果 。也就是前面说的“MapReduce” 。

推荐阅读