Latch contention on page free space (PFS) pages
The combination of a shallow B-Tree and random inserts across the index is prone to causing
The combination of a shallow B-Tree and random inserts across the index is prone to causing
page splits in the B-tree. In order to perform a page split, SQL Server must acquire shared (
)
latches at all levels, and then acquire exclusive (
) latches on pages in the B-tree that are
involved in the page splits. Also when concurrency is high and data is continually inserted and
deleted, B-tree root splits might occur. In this case, other inserts might have to wait for any
non-buffer latches acquired on the B-tree. This is manifested as a large number of waits on the
latch type observed in the
DMV.
The following script can be modified to determine the depth of the B-tree for the indexes on
the affected table.
PFS stands for Page Free Space, SQL Server allocates one PFS page for every 8088 pages
(starting with
=
) in each database file. Each byte in the PFS page records information
including how much free space is on the page, if it’s allocated or not and whether the page
stores ghost records. The PFS page contains information about the pages available for
allocation when a new page is required by an insert or update operation. The PFS page must
be updated in several scenarios, including when any allocations or deallocations occur. Since
the use of an update (UP) latch is required to protect the PFS page, latch contention on PFS
SH
EX
ACCESS_METHODS_HOBT_VIRTUAL_ROOT
sys.dm_os_latch_stats
PageID
1
SELECT o.name
AS
[
table
],
i.name
AS
[
index
],
indexProperty(object_id(o.name), i.name,
'indexDepth'
) +
indexProperty(object_id(o.name), i.name,
'isClustered'
)
AS depth
,
--clustered index depth reported doesn't count leaf level i.[
rows
]
AS
[
rows
],
i.origFillFactor
AS
[fillFactor],
CASE (indexProperty(object_id(o.name), i.name,
'isClustered'
))
WHEN
1
THEN
'clustered'
WHEN
0
THEN
'nonclustered'
ELSE
'statistic'
END
AS type
FROM sysIndexes
AS i
INNER
JOIN sysObjects
AS o
ON o.id = i.id
WHERE o.type =
'u'
AND indexProperty(object_id(o.name), i.name,
'isHypothetical'
) = 0
--filter out hypothetical indexes
AND indexProperty(object_id(o.name), i.name,
'isStatistics'
) = 0
--filter out statistics
ORDER
BY o.name;