Contract position in Seattle

March 9th, 2010

Do you know anybody that is interested in a 6mo-12mo contract position in Seattle (Redmond) area for a very interesting SQL Server project? Position requires good system architecture and development skills. Your main job will be writing T-SQL code for processing on a 24×7 mission critical system with a high transactions per second throughput. You will also be the escalation contact for operational aspects of monitoring and troubleshooting this project’s +50 SQL Server instances. Project involves Service Broker, Database Mirroring, Transactional Replication, Data Warehousing and ETL. You will need to either know these or be able to quickly come up to speed on these technologies.

If this sounds interesting to you, contact me. No agencies please.

Dealing with Large Queues

March 9th, 2010

On a project I’m currently involved with we have to handle a constant influx of audit messages for processing. The messages come from about 50 SQL Express instances located in data centers around the globe, delivered via Service Broker into a processing queue hosted on a mirrored database where an activated procedure shreds the message payload into relational tables. These tables are in turn replicated with transactional replication into a data warehouse database. after that the messages are deleted from the processing servers, as replication is set up not to replicate deletes. The system must handle a constant average rate of about 200 messages per second, 24×7, with spikes going up to 2000-3000 messages per second over periods of minutes to an hour.

When dealing with these relatively high volumes, it is inevitable that queues will grow during the 2000 msgs/sec spikes and drain back to empty when the incoming rate stabilizes again at the normal 200 msgs/sec rate. Service Broker does an excellent job at handling these non-connectivity periods, retains the audit messages and quickly delivers them when connectivity is restored.

What I noticed though is that sometimes the processing of the received messages could hit a threshold from where it could not recover. The queue processing would slow down to a rate that was bellow the incoming rate, and from that point forward the queue could just grow. I want to detail a bit the reason why this can happen and what I did to alleviate the problem.

Index Fragmentation

Every DBA knows about fragmentation. All database developers also understand fragmentation and how to avoid it. So we can skip ahead and … wait. Actually, what is index fragmentation? Lets go back to the whitepaper Microsoft SQL Server 2000 Index Defragmentation Best Practices. Even though the whitepaper is for SQL 2000, it was recently updated on March 2009 and is the most detailed whitepaper dealing with index fragmentation released by Microsoft I know of:

Fragmentation
Fragmentation exists when indexes have pages in which the logical ordering, based on the key value, does not match the physical ordering inside the data file.

Say you have an index with 9 rows, with the keys A, B, C, D, E, F, G, H and J. For our example, each page can fit 3 rows, and the database pages are in order in the database file: P1, P2 and P3. If the rows are (A,B,C) on P1, then (E,F,G) on P2 and (G, H, J) on P3 then the index is unfragmented. But if the row are (E,F,G) on P1 then (G,H,J) on P2 and (A,B,C) on P3 the page P3 is first in the key order, but last in the physical file order.

Index fragmentation affects the read performance when fetching pages into the buffer pool. This is because the Read-Ahead Manager issues read-ahead requests in contiguous fragments. When the index is fragmented the read-ahead manager will issue a large number of small read-aheads. When the index is contiguous the Read-Ahead Manager will issue a small number of large read-aheads. On traditional disk-head and spindle drives, the large number of small read requests caused by fragmentation results in drastic read throughput reduction. A large number of IO requests carries also a bigger user-to-kernel context switch baggage. Again, this is explained in the whitepaper I linked above:

To understand why fragmentation had such an effect on the DSS workload performance, it is important to understand how fragmentation affects the SQL Server read-ahead manager. For queries that scan one or more indexes, the SQL Server read-ahead manager is responsible for scanning ahead through the index pages and bringing additional data pages into the SQL Server data cache. The read-ahead manager dynamically adjusts the size of reads it performs based on the physical ordering of the underlying pages. When there is low fragmentation, the read-ahead manager can read larger blocks of data at a time, more efficiently using the I/O subsystem. As the data becomes fragmented, the read-ahead manager must read smaller blocks of data. The amount of read-aheads that can be issued is independent of the physical ordering of the data; however, smaller read requests take more CPU resources per block, resulting in less overall disk throughput.

What causes index fragmentation?

Fragmentation occurs either when the order of physical operations does not match the logical order of rows (eg. insert rows into a table in reverse order of the clustered index key) or when frequent update operations occur after the index is constructed: rows are deleted and new rows are inserted. One case is particularly aggravating: the insert page split, because the page split not only increases fragmentation, it also reduces the page fill factor of the index, further damaging performance.

Are Queues Fragmented?

Service Broker queues are backed by internal tables, and these tables have a clustered index on (status, conversation_group_id, priority, conversation_handle, queueing_order). Messages are constantly enqueued and dequeued into and from this internal table. The queueing operations are nothing else than inserts and deletes, and according to what we just discussed about how fragmentation occurs, they should get high index fragmentation.

However, there is one crucial difference between how data tables are used, in comparison with queues: Queues drain, meaning they are always near 0 records count. When they grow during spikes, the processing must be able to drain them back to 0, even as new messages are enqueued at normal rates. A table with no rows has no pages, so there is no fragmentation. So the expected behavior of queues is to hover around a low record count, where fragmentation has no performance impact, grow on spikes, get fragmented, but drain back to 0 and thus repairing themselves ‘on the fly’.

Or at least that’s how the theory goes…

Ghost Cleanup

SQL Server DELETE operations do no remove rows from indexes. Instead, the rows are simply marked as ‘ghosted’ and left in the page. It is the job of a dedicated task, namely the Ghost Cleanup task, to reclaim the space these rows occupy. More importantly, it is the Ghost Cleanup task’s job to deallocate any page that no longer contains any record and release these pages back to the database, as free pages. This is a performance improvement because DELETE operations can complete faster, and it also improves the performance of rollbacks. If you want to read more about how Ghost Cleanup operates, the best resource is Paul Randal’s article Inside the Storage Engine: Ghost cleanup in depth.

As I said, dequeue operations are in fact DELETE from the internal tables that back the Service Broker queues. When the RECEIVE statement is run, in fact an DELETE with OUTPUT occurs on this internal table. And as such, all the returned messages are in fact ghosted records left in the internal tables. The Ghost Cleanup has to come about and collect them, to reclaim the space and eventually free the space.

The Ghost Cleanup is calibrated to operate on a normal data table environment. It wakes every 5 seconds, reclaims ghosted records in up to 10 pages, then goes to sleep again. In addition, SELECT statements that encounter ghosted records during index scans place the page into a list so that the Ghost Cleanup collects it on its next pass. From SQL Server testing and customer feedback, this calibration balances the need to cleanup pages with the overhead of running the ghost cleanup just fine for a normal data table.

The problem with Service Broker queues is that they are not normal data tables: they are queues! Every single row is inserted and then deleted as fast as possible. No record is ever read twice. No record stays around. The queues are constantly growing, and constantly shrinking. On machines that are entirely dedicated to Service Broker processing it is not unusual to have all CPU and all I/O resources of the server dedicated to enqueuing and dequeuing messages into one single queue. In other words INSERT then quickly DELETE one row at a time, from all CPU cores, as fast as the I/O subsystem permits it. The Ghost Cleanup better keep up, as every enqueued message is deleted, and every deleted row is a ghosted record to be cleanup up. All of the sudden 10 pages every 5 seconds seems a bit short changed, when the rate of newly created ghosted records is 200 per second!

Crossing the Threshold

In my project we had an incident that causes a massive queue growth, to about 19 million messages. We expected the system to start draining as it usually did before, but it never did. It kept growing at a rate about 3 million a day, indicating that the processing could not keep up with the incoming rate of 200 msgs/sec. The processing was running as fast as possible, on a highly optimized procedure using the fastest set oriented message processing, similar to what I recommend in Writing Service Broker Procedures. After trying to speed up the IO system, moving the drives to fastest LUNs available in the attached SAN, the system could still no keep up. The disk metrics showed a lot of read requests of 8192. bytes. On a SQL Server disk a large number of read requests of 8k size are a tell-tale of fragmentation: no multi-page read-ahead occurs, indicating that the average contiguous fragment length is 1 page. Under normal circumstances one would check sys.dm_db_index_physical_stats for fragmentation but there is a small gotcha: this DMV does not show stats for queues!

A second observation occurred sometimes later: even after the queue drained, the allocated space was not reclaimed by the ghost cleanup. In fact I’ve seen a queue having 0 rows, but over 1 million pages allocated. The Skipped Ghosted Records/sec performance counter was showing over 200000 ghosted records skipped per second. It seems that the Ghost Cleanup was just unable to keep up with the nearly 200Gb size empty queue. Even running DBCC FORCEGHOSTCLEANUP could not improve the situation.

Queue Maintenance

When a DBA is faced with a fragmented index, it has a simple avenue: rebuild or reorganize the index. ALTER INDEX … REORGANIZE or ALTER INDEX … REBUILD, and maybe do it online to avoid system downtime. In fact there are quite a few scripts provided by the community for just such a task, like Michelle Ufford’s Index Defrag Script, and good DBAs always have their own, customized, flavor of index maintenance script in their tool belt.

But what about queues? There is no ALTER QUEUE … REBUILD nor ALTER QUEUE … REORGANIZE. How about the good ole’ (and now deprecated) DBCC DBREINDEX and DBCC INDEXDEFRAG? Nope, they don’t works on queues. But queues are backed by hidden tables, right? You can always find out the hidden table that backs a queue:

select it.name as internal_table_name, q.name as queue_name
from sys.internal_tables it
join sys.service_queues q on it.parent_object_id = q.object_id

This query returns the name of the internal table that backs each Service Broker queue in the database. Can we do our maintenance operations on them? ALTER INDEX ALL ON queue_messages_1003150619 REORGANIZE. Nope, no luck. DBCC DBREINDEX(’queue_messages_1003150619′)? But if you check the schema on which the internal table resides, its actually sys. Could DBCC DBREINDEX(’sys.queue_messages_1003150619′) work? Nope.

At this point I must use the deus ex machina: I know some internals of SQL Server from my Service Broker FTE days. One such information is this: statements run from the Dedicated Administrative Connection can have different binding rules. Is this the answer? YES:

Service Broker queues can be reindexed by running DBCC DBREINDEX on the internal table that backs the queue from the DAC connection. The internal table name must be prefixed with the sys schema name.

Fortunately this solution solved our problems. We’re running a job that, from a DAC connection, reindexes the internal table that backs the queue, even though the queue is empty. This operation reclaims the space consumed by millions of ghosted records back the the database:

dbcc dbreindex(’sys.queue_messages_1003150619′)

Conclusion

Just like tables, queues may require maintenance operations. But unlike tables, the DBA has no DDL at its disposal to do the job, except the DBCC DBREINDEX on the internal table, run from the DAC connection, which is a hack: a deprecated command, the DAC requirement, the internal table name digg from metadata… Hopefully, the problem will be addressed eventually and ALTER QUEUE … REINDEX and ALTER QUEUE … REORGANIZE will make it to the product.

Until then, should you be reindexing your queues every night? No. The conditions I encountered were caused by a very particular balance of server IO capacity, message incoming rate and triggered by a particularly high spike. But still, its good to know: if you ever do need to rebuild a queue because of high fragmentation or because of ghost cleanup … modesty… you can: find the name of the internal table behind the queue, open a DAC connection and run DBCC DBREINDEX.

I had this post on in standby for some time now, but since the SQLTuesday#4 topic is IO, IO, It’s Off To Disk We Go! I took the opportunity to finish it in time for the roundup.

DbccCommand Enumeration

February 22nd, 2010

The SMO libraries contain an enum for the DBCC commands: DbccCommand. But there is little explanation in the MSDN documentation what those commands are. I had a recent discussion with a developer who, understandably, expected a little cleaner explanation for the meaning of the mysterious enum values. So I decided to compile a table of links to the corresponding SQL Server DBCC command documentation. For well known undocumented commands, I’ve linked popular community articles. Some undocumented DBCC commands are very dangerous to use, obsolete or some are only for internal use, or simply I have no idea what they do, and I did not add any explanation for them.




Command Documentation Comments
ActiveCursors
AddExtendedProc
AddInstance
AuditEvent
AutoPilot Perhaps something to do with the Microsoft DataCenter AutoPilot?
Buffer Display pages from the buffer pool.
Bytes Reads the SQL Server process memory.
CacheProfile
CacheStats
CallFullText
CheckAlloc DBCC CHECKALLOC Checks the consistency of disk space allocation structures for a specified database.
CheckCatalog DBCC CHECKCATALOG Checks for catalog consistency within the specified database.
CheckConstraints DBCC CHECKCONSTRAINTS Checks the integrity of a specified constraint or all constraints on a specified table in the current database.
CheckDB DBCC CHECKDB Checks the logical and physical integrity of all the objects in the specified database.
CheckFileGroup DBCC CHECKFILEGROUP Checks the allocation and structural integrity of all tables and indexed views in the specified filegroup of the current database.
CheckIdent DBCC CHECKIDENT Checks the current identity value for the specified table and, if it is needed, changes the identity value.
CheckPrimaryFile
CheckTable DBCC CHECKTABLE Checks the integrity of all the pages and structures that make up the table or indexed view.
CleanTable DBCC CLEANTABLE Reclaims space from dropped variable-length columns in tables or indexed views.
ClearSpaceCaches
CollectStats
ConcurrencyViolation Discontinued in SQL 2008
CursorStats
DBRecover Use RESTORE DATABASE … WITH RECOVERY; instead.
DBReindex DBCC DBREINDEX Rebuilds one or more indexes for a table in the specified database.
DBReindexAll
DBRepair
DebugBreak Breaks the SQL Server process into debugger. Afaik this is inactive in the released bits.
DeleteInstance
DetachDB
DBCC dllname (FREE) Unloads the specified extended stored procedure DLL from memory.
DropCleanBuffers DBCC DROPCLEANBUFFERS Removes all clean buffers from the buffer pool.
DropExtendedProc
DumpConfig
DumpDBInfo Displays DBINFO structure for the specified database.
DumpDBTable Displays the contents of the DBTABLE structure
DumpLock
DumpLog
DumpPage
DumpResource
DumpTrigger
ErrorLog Recycles the errorlog. Use sp_cycle_errorlog instead.
ExtentInfo
FileHeader
FixAllocation
Flush
FlushProcInDB
ForceGhostCleanup Runs the ghost cleanup.
Free
FreeProcCache DBCC FREEPROCCACHE Removes all elements from the plan cache, removes a specific plan from the plan cache by specifying a plan handle or SQL handle, or removes all cache entries associated with a specified resource pool.
FreeSessionCache DBCC FREESESSIONCACHE Flushes the distributed query connection cache used by distributed queries against an instance of Microsoft SQL Server.
FreeSystemCache DBCC FREESYSTEMCACHE Releases all unused cache entries from all caches.
FreezeIO This is the ‘freeze’ phase of the SQL Writer VSS based database snapshot backup, as documented in A Guide for SQL Server Backup Application Vendors
Help DBCC HELP Returns syntax information for the specified DBCC command.
IcecapQuery Icecap is the name of one of the code profilers used inside Microsoft.
IncrementInstance
Ind Shows all pages in use by indexes of the specified table.
IndexDefrag DBCC INDEXDEFRAG Defragments indexes of the specified table or view.
InputBuffer DBCC INPUTBUFFER Displays the last statement sent from a client to an instance of Microsoft SQL Server.
InvalidateTextptr
InvalidateTextptrObjid
Latch
LogInfo
MapAllocUnit
MemObjList Use sys.dm_os_memory_objects instead.
MemoryMap
MemoryStatus DBCC MEMORYSTATUS Displays a snapshot of the current memory status of SQL Server.
Metadata
MovePage Do not use it.
NoTextptr
OpenTran DBCC OPENTRAN Displays information about the oldest active transaction and the oldest distributed and nondistributed replicated transactions, if any, within the specified database.
OptimizerWhatIf
OutputBuffer DBCC OUTPUTBUFFER Returns the current output buffer in hexadecimal and ASCII format for the specified session_id.
DBCC PAGE Prints out the contents of a SQL Server page. Although not in the SMO enum MSDN documentation, I could not let this one out of any DBCC write up…
PinTable
PerfMonStats
PersistStackHash
ProcCache DBCC PROCCACHE Displays information in a table format about the procedure cache.
PrtiPage Displays the page number pointed to by each row on the specified index page.
ReadPage
RenameColumn
RuleOff
RuleOn
SeMetadata
SetCpuWeight
SetInstance
SetIOWeight
ShowStatistics DBCC SHOW_STATISTICS Displays current query optimization statistics for a table or indexed view.
ShowContig DBCC SHOWCONTIG Displays fragmentation information for the data and indexes of the specified table or view.
ShowDBAffinity
ShowFileStats
ShowOffRules
ShowOnRules
ShowTableAffinity
ShowText
ShowWeights
ShrinkDatabase DBCC SHRINKDATABASE Shrinks the size of the data and log files in the specified database.
ShrinkFile DBCC SHRINKFILE Shrinks the size of the specified data or log file for the current database or empties a file by moving the data from the specified file to other files in the same filegroup, allowing the file to be removed from the database.
SqlMgrStats
SqlPerf DBCC SQLPERF Provides transaction log space usage statistics for all databases.
StackDump Creates a SQL Server process mini-dump
Tec
ThawIO This is the ‘thaw’ phase of the SQL Writer VSS based database snapshot backup, as documented in A Guide for SQL Server Backup Application Vendors
TraceOff DBCC TRACEOFF Disables the specified trace flags.
TraceOn DBCC TRACEON Enables the specified trace flags.
TraceStatus DBCC TRACESTATUS Displays the status of trace flags.
UnpinTable
UpdateUsage DBCC UPDATEUSAGE Reports and corrects pages and row count inaccuracies in the catalog views.
UsePlan
UserOptions DBCC USEROPTIONS Returns the SET options active (set) for the current connection.
WritePage Do not use it.

What deprecated features am I using?

January 12th, 2010

select instance_name as [Deprecated Feature]
  , cntr_value as [Frequency Used]
from sys.dm_os_performance_counters
where object_name = 'SQLServer:Deprecated Features'
and cntr_value > 0
order by cntr_value desc

Quick way to tell which deprecated feature are used on a running instance of SQL Server. The performance counters reset at each server start up, so the interogation is relevant only after the server was up for some time. This will not tell you where is the usage comming from, but will give you a very quick idea what deprecated features are used most frequently by your apps.

If the SQL Server is a named instance, you have to query the proper counter category: ‘MSSQL$<instancename>:Deprecated Features’

Applewood smoked Bacon milk Chocolate

November 28th, 2009
Mo\'s Bacon Bar

Mo's Bacon Bar