Guru Guide To Sql Server Architecture And Internals.pdf Guide
SELECT last_user_seek, last_user_scan, modifications FROM sys.dm_db_index_usage_stats WHERE database_id = DB_ID('SalesDB') AND object_id = OBJECT_ID('Orders'); The result: last_user_seek was yesterday. modifications was over 50,000.
That open transaction was preventing the transaction log from truncating. The log had grown to 200 GB. The ETL’s large update inside FactSales_Load had to wait for log space, causing log autogrowth events (zero-initialization → slow).
The buffer pool is a shared resource. Morning report’s KEEP hints or large scans polluted the cache. Guru Guide To Sql Server Architecture And Internals.pdf
He ran:
Index stats were stale. The query optimizer thought the scan was cheaper because it didn’t know the table had grown massively since the last stats update. The log had grown to 200 GB
He looked at sys.dm_tran_database_transactions during the ETL. One transaction had an old database_transaction_begin_time from 3 hours ago—an open transaction from a developer’s BEGIN TRAN in SSMS that was never committed or rolled back.
The transaction log is a circular log. It can’t reuse space if any active transaction holds onto a VLFL (virtual log file) even if it’s old. Morning report’s KEEP hints or large scans polluted
Here’s a story that teaches a real-world lesson from those internals. The Case of the Midnight Slowdown
SELECT * FROM sys.dm_os_buffer_descriptors WHERE database_id = DB_ID('SalesDB'); He saw that 40 GB of the buffer pool was filled with old data from a morning report. The ETL’s needed pages (the clustered index of Orders ) were being paged in from disk— couldn’t save it because the scan had already caused random I/O earlier.