Max*_*oke 6 sql-server sql-server-2012
我有一个被大量独立会话插入的数据库。每个会话写入不同的表,因此您会天真地期望它们都将并行进行。但是,通过检查sys.dm_os_wait_stats和sys.dm_os_latch_stats,我发现我实际上在DBCC PAGE报告为类型 11 的页面(即 PFS 页面)上遇到了大量的 PAGELATCH_* 等待。
所以基本上整个过程都变慢了,因为每个线程都在与其他线程竞争以分配新页面。
这种情况下的标准建议是:
DBCC TRACEON(1118, -1)强制服务器分配整个范围,而不是单个页面。我做了这两件事,它确实减少了 PFS 页面上的争用,但我现在看到PAGELATCH_EX页面上的一些争用DBCC PAGE告诉我是属于对象 ID 7 的数据页,即sysallocunits.
关于sysallocunits系统表用途的在线信息不多,我也找不到任何关于它的争用的信息。在改变这个表时,我似乎刚刚设法用瓶颈替换了我的分配瓶颈!
我想我可以通过将每个表放在自己的数据库中(然后不共享sysallocunits表)来减少争用,但这将是我宁愿避免的相当重要的架构更改。
有什么方法可以在sysallocunits不创建额外数据库的情况下减少争用?
编辑:根据要求,这是DBCC PAGE显示争用的页面之一的输出:
PAGE: (1:476)
BUFFER:
BUF @0x0000006143763A80
bpage = 0x0000004064D20000 bhash = 0x0000006301FCBAC0 bpageno = (1:476)
bdbid = 15 breferences = 2047 bcputicks = 48351
bsampleCount = 90 bUse1 = 32392 bstat = 0x10b
blog = 0x7a7a7a7a bnext = 0x0000000000000000
PAGE HEADER:
Page @0x0000004064D20000
m_pageId = (1:476) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x0
m_objId (AllocUnitId.idObj) = 7 m_indexId (AllocUnitId.idInd) = 0 Metadata: AllocUnitId = 458752
Metadata: PartitionId = 458752 Metadata: IndexId = 1 Metadata: ObjectId = 7
m_prevPage = (1:475) m_nextPage = (0:0) pminlen = 69
m_slotCnt = 34 m_freeCnt = 5546 m_freeData = 3089
m_reservedCnt = 0 m_lsn = (18391:146685:11) m_xactReserved = 0
m_xdesId = (0:588003648) m_ghostRecCnt = 0 m_tornBits = 208117691
DB Frag ID = 1
Allocation Status
GAM (1:2) = ALLOCATED SGAM (1:3) = NOT ALLOCATED PFS (1:1) = 0x40 ALLOCATED 0_PCT_FULL
DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED
Run Code Online (Sandbox Code Playgroud)
编辑 2:关于实际插入过程的更多细节。基本上:
(SecurityID, Date, FromSourceID)三元组的聚集索引。这些表可以有数百万行。ID。每个临时表最多可容纳 300,000 行。根据您提供的工作负载描述,您给分配单元带来了很大的压力,特别是因为您试图维护排序的负载(使用 IDENTITY 列和簇)。跟踪发生的分配会给元数据带来很大的压力 - 当然,除非您处于批量模式。
以下是潜在的解决方案: