Я рекомендую вам перейти на Использование таблиц в качестве очередей .Правильно реализованные очереди могут обрабатывать тысячи одновременно работающих пользователей и обслуживать до 1/2 миллиона операций постановки / удаления очереди в минуту.До SQL Server 2005 решение было громоздким и включало смешивание SELECT
и UPDATE
в одной транзакции и обеспечивало правильное сочетание подсказок блокировки, как в статье, на которую ссылается gbn.К счастью, начиная с SQL Server 2005 с появлением предложения OUTPUT, доступно гораздо более элегантное решение, и теперь MSDN рекомендует использовать предложение OUTPUT :
Вы можете использовать OUTPUT вприложения, которые используют таблицы в качестве очередей или для хранения промежуточных наборов результатов.То есть приложение постоянно добавляет или удаляет строки из таблицы
По сути, есть 3 части головоломки, которые нужно правильно настроить, чтобы это работало в высокой степени одновременно:
1) Вы должны разряжать атомарно.Вы должны найти строку, пропустить все заблокированные строки и пометить ее как «исключенную из очереди» в одной атомарной операции, и вот здесь вступает в игру предложение OUTPUT
:
with CTE as (
SELECT TOP(1) COMMAND, PROCESSED
FROM TABLE WITH (READPAST)
WHERE PROCESSED = 0)
UPDATE CTE
SET PROCESSED = 1
OUTPUT INSERTED.*;
2)Вы должны структурировать свою таблицу с помощью крайнего левого ключа кластеризованного индекса в столбце PROCESSED
.Если в качестве ID
использовался первичный ключ, то переместите его как второй столбец в кластерном ключе.Дискуссия о том, следует ли хранить некластеризованный ключ в столбце ID
, открыта, но я настоятельно рекомендую, чтобы не имел какие-либо вторичные некластеризованные индексы над очередями:
CREATE CLUSTERED INDEX cdxTable on TABLE(PROCESSED, ID);
3Вы не должны запрашивать эту таблицу другими способами, кроме как с помощью Dequeue.Попытка выполнения операций Peek или использование таблицы в качестве очереди и в качестве хранилища очень вероятно приведут к взаимоблокировкам и значительно снизят пропускную способность.
Комбинация атомарной очереди, подсказки READPAST при поиске элементов для удаления очереди и крайнего левого ключа в кластеризованном индексе на основе бита обработки обеспечивают очень высокую пропускную способность при высокой параллельной загрузке.