Question

I have a query which take a little while to run, so its run with the isolation level set to Read Uncommitted, the data can be dirty since its only used to give a quick overview of the system at a glance.

The query on a good day (first thing in the morning) takes around 3-15 seconds to run. (Date sorting slows it down, its instant without the sort)

But as the day starts it takes long and longer to run, it ends up taking > 2 minutes to run.

What I noticed is the query seems to get a LOT of OBJECT/PAGE locks when its executed.

What I don't understand is why its acquiring locks while its set to Read Uncommitted.


One of the index's that the query uses is set to use Row/Page locking.

My Q:

enter image description here

Does an index which is set to use row/page locks, cause the data to be locked when being accessed, even when the query is Read Uncommitted?

Was it helpful?

Solution

READ UNCOMMITTED isolation level changes behaviour of readers only. In READ COMMITTED and higher isolation level, when a task tries to read from a row, it first asks the lock manager for a shared lock on it. This request will be honored only if there is no existing exclusive lock on it from some other sessions, otherwise it will have to wait for it.

In READ UNCOMMITTED a reader will not request a shared lock, hence no chance of waiting on a possible exclusive lock to be released.

However, locking behaviour on update is the same regardless of isolation level used. Exclusive locks are still being taken in READ UNCOMMITTED (and held untill the end of transaction) as in any other pessimistic isolation level.

The increase in the time required for the query to finish can be attributed either to this, or to some resource contention, most likely memory related. Put simply, your query competes for the data cache with other queries running simultaneously.

Take a note of page life expectancy counter on various times of the day:

SELECT @@SERVERNAME AS [Server Name], [object_name], instance_name, cntr_value AS [Page Life Expectancy]
FROM sys.dm_os_performance_counters WITH (NOLOCK)
WHERE [object_name] LIKE N'%Buffer Node%' -- Handles named instances
AND counter_name = N'Page life expectancy' OPTION (RECOMPILE);

Also, to see what data is taking up the most space, use this query:

SELECT OBJECT_NAME(p.[object_id]) AS [Object Name], p.index_id, 
CAST(COUNT(*)/128.0 AS DECIMAL(10, 2)) AS [Buffer size(MB)],  
COUNT(*) AS [BufferCount], p.Rows AS [Row Count],
p.data_compression_desc AS [Compression Type]
FROM sys.allocation_units AS a WITH (NOLOCK)
INNER JOIN sys.dm_os_buffer_descriptors AS b WITH (NOLOCK)
ON a.allocation_unit_id = b.allocation_unit_id
INNER JOIN sys.partitions AS p WITH (NOLOCK)
ON a.container_id = p.hobt_id
WHERE b.database_id = CONVERT(int,DB_ID())
AND p.[object_id] > 100
GROUP BY p.[object_id], p.index_id, p.data_compression_desc, p.[Rows]
ORDER BY [BufferCount] DESC OPTION (RECOMPILE);

[This and other diagnostic queries can be found here: http://sqlserverperformance.wordpress.com/]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top