When you think of SQL Server, the first thing you think about is probably not SQL as host for messaging / queuing applications. However, in certain scenarios it definitely makes sense to implement messaging inside the SQL engine. In this session we will see the benefits of messaging applications inside SQL as well as what options you have when implementing it and their respective performance implications.
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Queuing Sql Server: Utilise queues to increase performance in SQL Server
1. Messages & Queues in SQL Server
Enhance performance by using queues in
SQL Server
2. Bio - Niels Berglund
Software Specialist - Derivco
Software Specialist - lots of production dev. plus figuring out
ways to "use and abuse" existing and new technologies
Author - "First Look at SQL Server 2005 for Developers"
Researcher / Instructor - DevelopMentor
Speaker - TechEd, DevWeek, SQL Pass, etc.
Longtime user of SQL Server
www.derivco.com
niels.it.berglund@gmail.com
@nielsberglund
2 |
10/28/201
Footer Goes Here
3 |
3. Derivco
World's leading development house for online
gaming software; Casino, Poker, Bingo etc.
Offices in Durban, Cape Town, Pretoria (soon)
Estonia, Hong Kong, Sweden, UK
Technology company
One of the world's largest install base of SQL Server's
(~300 SQL Server servers, multiple instances & db's).
SQL Server 2008 / 2012, research into 2014
Hadoop, Windows Azure
.NET 4.5, SignalR, WebSockets, mobile (Android, iOS)
WE ARE HIRING
5. Background
In certain scenarios beneficial to off-load work to other
processes/threads.
In SQL Server we have no real way to control threading
Historically difficult to create messaging applications in SQL
Server, due to queuing is highly concurrent.
how do we ensure that multiple consumers does not block each
other
how do we de-queue without causing deadlocks
etc.
SQL Server 2005 introduced new functionality which makes
it easier to remove a de-queued row and return it to the
caller in one atomic statement:
DELETE TOP(x)
OUTPUT statement
6. De-queuing old vs. new
--old way
DECLARE @tab TABLE(RowID bigint, MsgTypeID int, Msg varchar(500),
EnqueueDate datetime2)
INSERT INTO @tab
SELECT TOP (1) * FROM dbo.tb_QueueTabClIdx WITH(UPDLOCK, READPAST)
DELETE clix FROM dbo.tb_QueueTabClIdx clix
JOIN @tab t ON clix.RowID = t.RowID
--new way
DECLARE @tab TABLE(RowID bigint, MsgTypeID int, Msg varchar(500),
EnqueueDate datetime2)
DELETE TOP(1) dbo.tb_QueueTabClIdx WITH(ROWLOCK, READPAST)
OUTPUT deleted.RowID, deleted.MsgTypeID, deleted.Msg, deleted.EnqueueDate
INTO @tab(RowID, MsgTypeID, Msg, EnqueueDate)
7. Queue types
Heap queue
backed by heap table
heap table is a table with no clustered index
cannot guarantee order of en-queue, de-queue
useful for specific queuing scenarios
beware of side effects (data growth)
Ordered queue (FIFO, LIFO)
First In First Out, Last In First Out
in LIFO queues beware of hot-spots (inserting, deleting same group of
rows)
backed by table with clustered index (can be non-unique or unique)
de-queuing has to be done with an ORDER BY clause
SQL Server Service Broker Queue (SSB Queue)
Bound queues (more later)
8. De-queuing ordered queues
De-queue has to be done with an ORDER BY clause
Unfortunately DELETE does not support ORDER BY
By using a CTE we can however do it in a very efficient way
the query will execute as a DELETE,
NOT SELECT followed by DELETE, nor as SELECT in context
of a DELETE
SELECT automatically taking UPDATE lock
;WITH delCte
AS
(
SELECT TOP(1) RowID, Msg, EnqueueDate
FROM dbo.tb_QueueTabClIdx WITH(ROWLOCK, READPAST)
ORDER BY RowId
)
DELETE delCte
OUTPUT deleted.*
9. SSB queues
SSB allows internal or external processes to send
and receive guaranteed, asynchronous messages
by using extensions to DML
It has the concept of queues, meant for use by SSB
When using it in a "normal" queuing application, it
has several short-comings:
convoluted way to en-queue messages
rigid structure
performance
One big plus though: Activation
stored procedure that automatically is activated when a
message is en-queued on the SSB queue.
can control concurrency
10. Performance I
Multiple producers running concurrently
One consumer running in parallel
Each producer en-queuing one record
running in a tight loop, 10,000 times
Consumer started together with the
producers, de-queuing until no more data.
11.
12. Bound queues
High volume inserts/deletes causes problems in
a db:
heap table unlimited growth
statistics are never up to date
auto updates of statistics constantly kicking in,
creating jagged CPU patterns and throughput
new pages constantly allocated, de-allocated stresses internal allocation structures
Quite a few high performing queuing
applications are using a bound queue in a ringbuffer scenario
minimizes memory allocation, de-allocation
13. Table backing ring-buffer
CREATE TABLE dbo.tb_QueueTabRingBuffer
(
MsgSlot BIGINT NOT NULL
, MessageID BIGINT NULL
, MsgTypeID int NULL
, EnqueueDate datetime2 NOT NULL
, Msg char(500) NOT NULL
, ReferenceCount TINYINT NOT NULL
)
14. Using a ring-buffer like table
After creation of table, prefill with data (keep track of how
many rows inserted)
To enqueue:
create a new message id
find the next available slot
update the message column and add one to the reference count
To de-queue
find the smallest message id that has not yet been de-queued.
read and return the message column
decrement reference count, marking the slot as available.
We need to be able to extremely efficiently locate the next
available slot
For this we use a sequence object
15. Sequence object
A high scale data structure to generate "next number"
quite a few "neat" features
Introduced in SQL Server 2012
When used in conjunction with the modulo operator (%)
we can efficiently get next slot etc.
CREATE SEQUENCE dbo.seq_Test AS BIGINT
START WITH 1 INCREMENT BY 1
CACHE 5000;
GO
SELECT NEXT VALUE FOR dbo.seq_Test;
16. En-queuing
When en-queuing into a ring-buffer, the en-queue may
block if no available slots.
Need to handle that in en-queue code (not shown below)
DECLARE
DECLARE
DECLARE
DECLARE
@enqueuSequence bigint;
@slot int;
@QueueSize int = 5000;
@msg char(500) = 'this is a new message';
--grab the next value, and slot
SET @enqueuSequence = NEXT VALUE FOR dbo.seq_Enqueue;
SET @Slot = @enqueuSequence % @QueueSize
--do the update
UPDATE dbo.tb_QueueTabRingBuffer WITH(ROWLOCK)
SET EnqueueDate = SYSDATETIME(), Msg = @Msg, MessageID =
@enqueuSequence, MsgTypeID = 2, ReferenceCount = 1
WHERE MsgSlot = @Slot AND ReferenceCount = 0
17. De-queuing
De-queuing is similar to en-queue. Need however to
ensure that the de-queue sequence does not out of
synch with the en-queue.
DECLARE @dequeuSequence bigint;
DECLARE @slot int;
DECLARE @queueSize int = 5000;
--grab the next MessageID, and slot
SET @dequeuSequence = NEXT VALUE FOR dbo.seq_Dequeue;
SET @Slot = @dequeuSequence % @QueueSize
UPDATE dbo.tb_QueueTabRingBuffer WITH(ROWLOCK)
SET EnqueueDate = SYSDATETIME(), MessageID = NULL, MsgTypeID = NULL
, Msg = 'dummy', ReferenceCount = 0
OUTPUT deleted.*
WHERE MsgSlot = @Slot AND MessageID = @dequeuSequence
AND ReferenceCount = 1;
18.
19. Summary
Implementing efficient queuing in SQL Server is definitely
doable
SQL Server 2008R2
the best table structure for overall performance is a queue
backed by clustered non-unique index
for certain specialized scenarios a heap-table can come into play
(beware of data growth)
SQL Server 2012
a ring-buffer like structure using sequence objects are the
absolutely best performing table structure
beware of more convoluted code to keep the en-queue and dequeue in synch
SQL Server Service Broker
too convoluted, not enough performance
activation procedures its strong point
Editor's Notes
Do not take any notice of the absolute numbers - the tests run on a low-end machine, in a VM. Look at the relations between the various structures.
Do not take any notice of the absolute numbers - the tests run on a low-end machine, in a VM. Look at the relations between the various structures.