I still have to wonder on the appropriate use of NOLOCK. Even if the data does not change in a table, is NOLOCK that much better than a standard shared lock?
Yes, it can be. NOLOCK can prevent other tasks from deadlocking.
The jihad against NOLOCK is somewhat overdone. The only major difference between NOLOCK and READ COMMITTED (RC) is that modified can be read vs not read (you can mitigate an additional scan issue with a server setting). RC still does allow non-repeatable reads and phantom reads, just like NOLOCK does.
So whats the server setting? Apologies if its already been posted. I have stacks of nolock code (not my idea) and would be open to any improvements.
I wouldn't necessarily recommend that you leave this in place -- then again, you might want to review that possibility for yourself, depending on how much you want to use NOLOCK -- but for specific cases when you really want to use NOLOCK but not have to deal with allocation scans (which can indeed cause bad-data issues with NOLOCK not seen with RC), then you can run:
EXEC sys.sp_configure 'cursor threshold', 5000; --<<-- anything other than -1 will stop all allocation scans across the instance:
-- MS states that you need to leave "small" sets to be sync; as a rough base, I consider 5,000 rows or less a "small" set.
Once you've processed your critical NOLOCK query(ies), you can reset the threshold:
EXEC sys.sp_configure 'cursor threshold', -1;
Ref (Paul White): https://sqlperformance.com/2015/01/t-sql-queries/allocation-order-scans
SQL DBA,SQL Server MVP(07, 08, 09) Prosecutor James Blackburn, in closing argument in the Fatal Vision murders trial: "If in the future, you should cry a tear, cry one for them [the murder victims]. If in the future, you should say a prayer, say one for them. And if in the future, you should light a candle, light one for them."