Использование таблицы базы данных в качестве очереди
Я хочу использовать таблицу базы данных в качестве очереди. Мне нужно вставлять в нее элементы и извлекать их в порядке вставки (FIFO). Моя главная задача — производительность, так как у меня происходит тысячи таких транзакций каждую секунду. Я хочу использовать SQL-запрос, который позволит мне получить первый элемент без необходимости сканировать всю таблицу. При этом я не удаляю строку, когда читаю ее. Поможет ли в этом случае запрос SELECT TOP 1 ...? Нужны ли мне какие-либо специальные индексы?
5 ответ(ов)
Если вы не удаляете обработанные строки, вам нужно будет установить какой-то флаг, который указывает, что строка уже была обработана.
Создайте индекс на этом флаге и на колонке, по которой вы собираетесь сортировать.
Разделите вашу таблицу по этому флагу, чтобы обработанные транзакции не загромождали ваши запросы.
Если вы действительно будете получать 1.000
сообщений каждую секунду, это приведет к 86.400.000
строкам в день. Возможно, имеет смысл подумать о способах очистки старых строк.
Все зависит от вашего движка базы данных/реализации.
В моем случае простые очереди в таблицах со следующими столбцами:
id / задача / приоритет / дата_добавления
обычно работают хорошо.
Я использовал приоритет и задачу для группировки задач, и в случае дублирования задачи выбирал ту, которая имела более высокий приоритет.
И не переживайте — для современных баз данных "тысячи" записей — это ничто особенное.
Возможно, добавление LIMIT 1 к вашему оператору SELECT поможет. Это позволит получить результат после первого совпадения.
Поскольку вы не удаляете записи из таблицы, вам нужно создать составной индекс на (processed, id)
, где processed
— это столбец, который указывает, была ли текущая запись обработана.
Наилучший вариант — создать разделённую таблицу для ваших записей и сделать поле PROCESSED
ключом разбиения. Таким образом, вы сможете создать три или более локальных индекса.
Однако, если вы всегда обрабатываете записи в порядке id
и имеете только два состояния, обновление записи будет означать просто извлечение записи из первого листа индекса и добавление её в последний лист.
В данный момент обрабатываемая запись всегда будет иметь наименьший id
среди всех необработанных записей и наибольший id
среди всех обработанных записей.
Создание кластерного индекса по столбцу даты (или автоинкрементному столбцу) поможет сохранить строки в таблице в порядке индекса и обеспечит быстрый доступ к данным с помощью индекса при выполнении запроса ORDER BY
по индексированному столбцу. Использование TOP X
(или LIMIT X
, в зависимости от вашей СУБД) позволит получать только первые X элементов из индекса.
Предупреждение по производительности: всегда проверяйте планы выполнения ваших запросов (на реальных данных), чтобы убедиться, что оптимизатор не делает неожиданных вещей. Также старайтесь проводить бенчмаркинг ваших запросов (опять же на реальных данных), чтобы принимать обоснованные решения.
Сброс начального значения идентификатора после удаления записей в SQL Server
Postgres: Как повысить пользователя до суперпользователя?
Как вставить несколько строк в SQLite?
Решения для INSERT OR UPDATE в SQL Server
Выполнение SQL из файла в SQLAlchemy