Используя таблицу базы данных как очередь

Я хочу использовать таблицу базы данных в качестве очереди. Я хочу вставить в него и взять элементы от него во вставленном порядке (FIFO). Мое основное внимание является производительностью, потому что у меня есть тысячи этих транзакций каждую секунду. Таким образом, я хочу использовать SQL-запрос, который дает мне первый элемент, не ища целую таблицу. Я не удаляю строку, когда я считал ее. ИЗБРАННЫЙ TOP 1..... помогает здесь? Я должен использовать какие-либо специальные индексы?

43
задан Brian Tompsett - 汤莱恩 26 February 2017 в 21:39
поделиться

7 ответов

Я бы использовал поле IDENTITY в качестве первичного ключа, чтобы обеспечить уникальный инкрементирующий ID для каждого элемента очереди, и приклеил бы к нему кластерный индекс. Это будет представлять порядок, в котором элементы стоят в очереди.

Для сохранения элементов в таблице очереди во время их обработки, вам понадобится поле "status" для указания текущего статуса конкретного элемента (например, 0= ожидание, 1=обработан, 2=обработан). Это необходимо для того, чтобы элемент не обрабатывался дважды.

При обработке элементов в очереди необходимо найти следующий элемент в таблице НЕ обработанный в данный момент. Это должно быть сделано таким образом, чтобы предотвратить одновременную обработку одного и того же элемента несколькими процессами, как показано ниже. Обратите внимание на подсказки table hints UPDLOCK и READPAST, о которых Вы должны знать при реализации очередей.

например, внутри sproc, что-то вроде этого:

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 - я просто подумал, что брошу это в микс!

32
ответ дан 26 November 2019 в 23:05
поделиться

Если вы не удалите свои обработанные строки, вам понадобится какой-то флаг, который указывает, что строка уже обработана.

Поместите индекс на этот флаг, а на столбец вы собираетесь заказать.

Разделите свой стол над этим флагом, поэтому транзакции для взыскания не заставляют ваши запросы.

Если вы действительно получите 1 000 сообщений каждую секунду, это приведет к 86,400 000 в день. Вы можете подумать о каком-то способе очистить старые ряды.

7
ответ дан 26 November 2019 в 23:05
поделиться

Это не будет никаких проблем, пока вы используете что-то, чтобы отслеживать DateTime вставки. Смотрите здесь для вариантов MySQL . Вопрос в том, только ли только в последний раз понадобится абсолютный последний представленный товар или должен ли вам соблюдать итерацию. Если вам нужно итератай, то то, что вам нужно сделать, это захватить кусок с помощью , заказа на по выписку , петлю, а запомнить последнее dateTime , чтобы вы могли использовать это, когда вы можете использовать Возьмите свой следующий кусок.

3
ответ дан 26 November 2019 в 23:05
поделиться

Возможно, добавление предельного = 1 в ваше выделенное утверждение поможет ... Принудительно возврат после одного матча ...

2
ответ дан 26 November 2019 в 23:05
поделиться

Все зависит от движка/внедренности вашей базы данных.

Для меня работают простые очереди на таблицах со следующими столбцами:

id / task / priority / date_added

обычно.

Я использовал приоритет и задачу для группировки задач, и в случае двойной задачи я выбрал задачу с большим приоритетом.

И не волнуйтесь - для современных баз данных "тысячи" - ничего особенного.

4
ответ дан 26 November 2019 в 23:05
поделиться

Можно использовать preg _ match _ all для разделения последовательности на гласные/негласные части и обработки этого.

например. что-то вроде

preg_match_all("/(([aeiou])|([^aeiou]+)*/",
    $in,
    $out, PREG_PATTERN_ORDER);

В зависимости от конкретных потребностей может потребоваться изменить размещение () * +? в регексе.

-121--3950572-

Apple подтверждает, что все приложения, доступные в магазине приложений, можно запускать на iPad См. следующую ссылку: http://www.apple.com/ipad/app-store/

При этом Cocos2D является просто библиотекой opensource, которая состоит в основном из кода Objective-c/Cocoa. Все будет хорошо.

Также программа для разработчиков Apple (ссылка здесь: http://developer.apple.com/iphone ) упоминает: «iPhone Developer Program Членов может начать разработку приложений для iPad с iPhone SDK 3,2 бета».

Продолжайте и начинайте...

-121--3690534-

Поскольку записи из таблицы не удаляются, необходимо иметь составной индекс для (обработанная, идентификатор) , где обработанная - столбец, указывающий, была ли обработана текущая запись.

Лучше всего создать секционированную таблицу для ваших записей и сделать поле PROCESSED ключом секционирования. Таким образом, можно сохранить три или более локальных индексов.

Однако если вы всегда обрабатываете записи в порядке id и имеете только два состояния, обновление записи будет означать просто извлечение записи из первого листа индекса и добавление ее к последнему листу

Текущая обработанная запись всегда будет иметь наименьший id из всех необработанных записей и наибольший id из всех обработанных записей.

2
ответ дан 26 November 2019 в 23:05
поделиться

Создайте кластерный индекс над столбцом даты (или автоинкремента). Это позволит сохранить строки в таблице примерно в порядке индексов и обеспечит быстрый доступ к индексам, когда вы ORDER BY проиндексировали столбец. При использовании TOP X (или LIMIT X, в зависимости от Вашей RDMBS), из индекса будут извлечены только первые х элементов.

Предупреждение о производительности: вы всегда должны просматривать планы выполнения ваших запросов (на реальных данных), чтобы убедиться, что оптимизатор не делает неожиданных вещей. Также постарайтесь сравнить свои запросы (опять же на реальных данных), чтобы иметь возможность принимать обоснованные решения.

2
ответ дан 26 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: