Я переношу очередь на диск в память SQL Server 2016 для реализации очереди.UPDATE из таблицы в SQL Собственная хранимая процедура (Hekaton)
Это мой формат очереди:
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
Это мой родной Enqueue
SQL Server хранимые процедуры:
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
Я пытаюсь записать процедуру Dequeue
нативный SQL Server хранится, но У меня возникают некоторые трудности с тем, как реализовать UPDATE
, используя результаты таблицы SELECT или переменной.
До сих пор я пытался:
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
Но я получаю эту ошибку:
Subqueries (queries nested inside another query) is only supported in SELECT statements with natively compiled modules.
Так что я попробовал другой подход, используя переменную для хранения результата.
Сначала я создал тип таблицы:
CREATE TYPE dbo.SimpleDequeue
AS TABLE
(
MsgId BIGINT NOT NULL PRIMARY KEY NONCLUSTERED,
Payload INT NOT NULL
)
WITH (MEMORY_OPTIMIZED=ON)
GO
До сих пор так хорошо, то я пытался использовать его:
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
Я получаю эту ошибку:
Must declare the scalar variable "@result".
(только при использовании @result
на WHERE @result.MsgId = dbo.SimpleQueue.MsgId
)
Вот старый Dequeue процесс с использованием таблиц диска SQL Server:
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
Как я могу сделать, что UPDATE и выводить обновленные значения (с высокой производительностью, так как это очень важно)?
Относительно ORDER BY I опущен, что пункт о цели. В соответствии с MSDN «Строки можно извлекать в соответствии с порядком, указанным при создании индекса. Если порядок сортировки индекса соответствует порядку сортировки, требуемому для конкретного запроса, например, если индексный ключ соответствует предложению ORDER BY, нет необходимости для сортировки строк как части выполнения запроса ». Источник: https://msdn.microsoft.com/en-us/library/dn133166.aspx –
Я пытался использовать UPDATE dbo.SimpleQueue \t SET IsDeleted = 1 \t WHERE dbo.SimpleQueue.MsgId IN (@result), но я все равно получаю эту ошибку: должен объявить скалярную переменную «@result». Пожалуйста, не забывайте, что вы не можете использовать подзапросы в ** собственных хранимых процедурах ** –
@ JoãoAntunes, ну, у меня нет опыта работы с таблицами в памяти (обязательно посмотрите!), Но это больше похоже на объяснение как работает оптимизатор, поэтому нет необходимости в двойном ORDER BY, если сортировка уже подходит. В общем, нет абсолютно никакой гарантии, в каком порядке вы получите свой результат - если вы не укажете ORDER BY в самом внешнем запросе (то же самое с подзапросами ...) – Shnugo