Производительность MySQL - выбор и удаление из большой таблицы

94
9

У меня есть большая таблица под названием "queue". Сейчас у него 12 миллионов записей.

CREATE TABLE 'queue' (
'id' int(11) unsigned NOT NULL AUTO_INCREMENT,
'userid' varchar(64) DEFAULT NULL,
'action' varchar(32) DEFAULT NULL,
'target' varchar(64) DEFAULT NULL,
'name' varchar(64) DEFAULT NULL,
'state' int(11) DEFAULT '0',
'timestamp' int(11) DEFAULT '0',
'errors' int(11) DEFAULT '0',
PRIMARY KEY ('id'),
UNIQUE KEY 'idx_unique' ('userid','action','target'),
KEY 'idx_userid' ('userid'),
KEY 'idx_state' ('state')
) ENGINE=InnoDB;

Несколько рабочих PHP (150) используют эту таблицу одновременно.

Они выбирают запись, выполняют сетевой запрос с использованием выбранных данных и затем удаляют запись.

Я получаю смешанное время выполнения из запросов выбора и удаления. Является ли команда delete блокировкой таблицы?

Какой был бы лучший подход для этого сценария?

SELECT запись + запрос NETWORK + УДАЛИТЬ запись

SELECT-запись + запрос NETWORK + запись MARK как завершенная + DELETE заполняет записи с использованием cron время от времени (я не хочу еще большую таблицу).

Примечание: очередь получает новые записи каждую минуту, но запрос INSERT здесь не является проблемой.

Любая помощь приветствуется.

спросил(а) 2017-12-03T21:24:00+03:00 2 года, 7 месяцев назад
1
Решение
55

"Не ставьте в очередь, просто сделайте это". То есть, если задачи выполняются довольно быстро, лучше просто выполнить действие, а не ставить его в очередь. Базы данных не создают хороших механизмов очередей.

DELETE не блокирует таблицу InnoDB. Однако вы можете написать DELETE который кажется таким озорным. Давайте посмотрим ваш фактический SQL, чтобы мы могли работать над его улучшением.

12M записей? Это огромное отставание; что?

Сократите типы данных, чтобы таблица не была гигабайтом:

    action - это всего лишь небольшой набор возможных значений? Нормализовать его до 1-байтового ENUM или TINYINT UNSIGNED. Точно для state - конечно, ему не нужен 4-байтовый код? Нет необходимости в INDEX(userid) поскольку уже есть индекс (UNIQUE), начинающийся с userid. Если state имеет только несколько значений, индекс не будет использоваться. Давайте посмотрим на ваши запросы в очереди и dequeue, чтобы мы могли обсудить, как либо избавиться от этого индекса, либо сделать его "составным" (и полезным). Какое текущее значение MAX(id)? Является ли угрозой превысить ваш текущий предел около 4 миллиардов для INT UNSIGNED? Как PHP использует очередь? Влияет ли он на предмет через транзакцию InnoDB? Это побеждает любой параллелизм! Или это изменяет state. Покажите нам код; возможно, блокировка & разблокировка может быть менее инвазивной. Должна быть предусмотрена возможность запуска одного автономного UPDATE для захвата строки и ее id. Затем, сделайте автокомментированный DELETE с очень небольшим воздействием. Я не вижу хорошего индекса для захвата ожидающего элемента. Опять же, посмотрим код. 150 кажется много - вы экспериментировали с меньшим количеством? Они могут спотыкаться друг над другом. Включен ли Slowlog (с низким значением long_query_time)? Если это так, мне интересно, что такое "худший" запрос. В подобных ситуациях ответ может быть неожиданным.

ответил(а) 2017-12-03T22:59:00+03:00 2 года, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема