I'm migrating a queue in disk to in memory SQL Server 2016 to implement a queue.
This is my queue format:
CREATE TABLE dbo.SimpleQueue
(
MsgId BIGINT NOT NULL PRIMARY KEY NONCLUSTERED IDENTITY(1, 1),
Payload VARCHAR(7500) NOT NULL,
IsDeleted BIT NOT NULL
) WITH (MEMORY_OPTIMIZED=ON)
GO
This is my Enqueue
native SQL Server stored procedure:
CREATE PROCEDURE dbo.Enqueue(@Payload VARCHAR(7500), @IsDeleted BIT)
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
(TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'english')
INSERT INTO dbo.SimpleQueue (Payload, IsDeleted) VALUES (@Payload, @IsDeleted);
END
GO
I'm trying to write down the Dequeue
native SQL Server stored procedure, but I'm having some difficulties on how to implement an UPDATE
using results of a SELECT or a variable table.
So far I tried:
CREATE PROCEDURE dbo.Dequeue(@BatchSize INT = 1)
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
( TRANSACTION ISOLATION LEVEL = SNAPSHOT,LANGUAGE = 'english' )
UPDATE dbo.SimpleQueue
SET IsDeleted=1
WHERE MsgId = (
SELECT TOP(@BatchSize) MsgId, Payload
FROM dbo.SimpleQueue
WHERE IsDeleted = 0)
END
GO
But I get this error:
Subqueries (queries nested inside another query) is only supported in SELECT statements with natively compiled modules.
So I tried a different approach by using a variable to store the result.
First I created a Table type:
CREATE TYPE dbo.SimpleDequeue
AS TABLE
(
MsgId BIGINT NOT NULL PRIMARY KEY NONCLUSTERED,
Payload INT NOT NULL
)
WITH (MEMORY_OPTIMIZED=ON)
GO
So far so good, then I tried to use it:
CREATE PROCEDURE dbo.Dequeue(@BatchSize INT = 1)
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
( TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'english')
DECLARE @result dbo.SimpleDequeue;
INSERT @result
SELECT TOP(@BatchSize) MsgId, Payload FROM dbo.SimpleQueue
WHERE IsDeleted = 0
UPDATE dbo.SimpleQueue
SET IsDeleted = 1
WHERE
@result.MsgId = dbo.SimpleQueue.MsgId
SELECT MsgId, Payload FROM @result
END
GO
I get this error:
Must declare the scalar variable "@result".
(only when is using @result
on WHERE @result.MsgId = dbo.SimpleQueue.MsgId
)
Here is the old dequeue process using in disk SQL Server tables:
CREATE PROCEDURE dbo.DequeueInDisk
@BatchSize INT = 1
AS
BEGIN
SET NOCOUNT ON;
WITH
cte AS (
SELECT TOP(@BatchSize) Payload
FROM dbo.SimpleQueue WITH (ROWLOCK, READPAST)
ORDER BY MsgId
)
DELETE FROM cte OUTPUT deleted.Payload;
END
How can I make that UPDATE and OUTPUT the updated values (with high performance, since this is critical)?