我想使用数据库表作为队列。我想插入其中并按插入顺序(FIFO)从中获取元素。我主要考虑的是性能,因为我每秒有数千个这样的交易。所以我想使用一个 SQL 查询,它可以在不搜索整个表的情况下为我提供第一个元素。阅读时我不会删除一行。 SELECT TOP 1 ..... 在这里有帮助吗? 我应该使用任何特殊索引吗?
最佳答案
我会使用一个 IDENTITY 字段作为主键,为每个排队的项目提供唯一递增的 ID,并在其上粘贴一个聚集索引。这将表示项目排队的顺序。
要在处理项目时将项目保留在队列表中,您需要一个“状态”字段来指示特定项目的当前状态(例如 0=等待,1=正在处理,2=已处理)。这是防止一个项目被处理两次所必需的。
当处理队列中的项目时,您需要找到表中当前未处理的下一个项目。这需要以这样一种方式进行,以防止多个进程同时拾取同一项目进行处理,如下所示。注意 table hints UPDLOCK 和 READPAST 在实现队列时应该注意。
例如在存储过程中,像这样:
DECLARE @NextID INTEGER
BEGIN TRANSACTION
-- Find the next queued item that is waiting to be processed
SELECT TOP 1 @NextID = ID
FROM MyQueueTable WITH (UPDLOCK, READPAST)
WHERE StateField = 0
ORDER BY ID ASC
-- if we've found one, mark it as being processed
IF @NextId IS NOT NULL
UPDATE MyQueueTable SET Status = 1 WHERE ID = @NextId
COMMIT TRANSACTION
-- If we've got an item from the queue, return to whatever is going to process it
IF @NextId IS NOT NULL
SELECT * FROM MyQueueTable WHERE ID = @NextID
如果处理一个项目失败,你想稍后再试吗?如果是这样,您需要将状态重置为 0 或其他内容。这将需要更多思考。
或者,不要将数据库表用作队列,而是使用 MSMQ 之类的东西 - 我只是想把它混在一起!
关于sql - 使用数据库表作为队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2177880/