在现实的生产环境中,有可能遇到高并发insert的应用.在此应用时由于堆表(Heap)和聚集表的结构不同导致在高并发的情形下insert效率不尽相同.接下来我会简单的以测试用例来简要说明.并举例说明如果提高聚集表下高并发插入效率.
在测试前我们先简单了解下堆表和聚集表都是如何完成插入操作的.
关于堆表和聚集表的介绍:SQL Server 索引知识-结构,实现
堆表Insert
方式1 a获得第一个IAM页
b 获取与之相关的PFS页,从中找到第一个能容纳Insert数据行大小的数据页
c 如果没有找到相应数据页则转到下一个IAM页然后重复b操作
d 如果到最后的IAM页还是没有找到可容纳的数据页则分配新的扩展区(extent)
e Insert指定行
方式2 a 获取所有IAM页
b 获取与之相关的PFS页(s)找到能容纳数据行(s)的数据页(s)
c 如果没有相关数据页,或者没有足够的相关数据页,分配新扩展区(extent)
d 插入相应的行(s)
聚集表Insert
由于聚集表本身的特性,插入数据的时的数据行必须在叶子节点的特定位置.
a 获取root页
b 通过B-tree需找到指定插入行的数据页的位置
c 如果此时数据页中空间可以容纳此行,则insert,如果不能则分配新数据页或者页分裂.然后insert
注:页分裂相对于页内的DML操作(insert,update)消耗巨大,页分裂的频率上升会明显影响实例的性能
测试用例
测试工具: sqlquerystress
测试环境:sql2008R2,3台不同服务器上分别安装运行sqlquerystress,100 threads/server
2000 times/thread
注意:如要模拟高并发需多台机器共同执行,单台即便多threads测试,测试结果也不能合理反应高并发情况.
测试脚本
我们在相应的机器上sqlquerystress中分两次(堆表,聚集表)分别运行insert into tempdb.dbo.tx(str1) select 'aa'测试
然后比较堆表,聚集表相关的性能指标.(Batch requests/sec,elapsed time,wait stats)
堆表
create table t1(id int identity(1,1),str1 char(5))goDBCC SQLPERF ("sys.dm_os_wait_stats", CLEAR)with NO_INFOMSGS -----run the sqlquerystress at three servers-----100 threads /per server-----2000 times /threadselect * from sys.dm_os_wait_stats order by waiting_tasks_count desc
聚集表
checkpointdbcc dropcleanbufferscreate table t2(id int identity(1,1) PRimary key,---clustered index defaultstr1 char(5))DBCC SQLPERF ("sys.dm_os_wait_stats", CLEAR)with NO_INFOMSGS -----run the sqlquerystress at three servers-----100 threads /per server-----2000 times /threadselect * from sys.dm_os_wait_stats order by waiting_tasks_count desc
测试结果
执行时的吞吐量Batch requests/sec
可以看出在我们的测试环境下堆表的吞吐量是聚集表的2倍以上 图1-1
新闻热点
疑难解答