2013-12-09 2 views
1

Я запускаю службу, которая принимает пользовательский запрос и добавляет его в таблицу с именем «queue», которая имеет 3 поля: userid, и processed.Оптимизация базы данных mysql - Список задач ест мой сервер

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

К сожалению, я не очень много знаю об оптимизации тузда и моем сценарии обработки (что я бег 50 версий параллельно) использует запросы как те:

SELECT * FROM `queue` WHERE `processed` = 0 ORDER BY `queue`.`queuenumber` 

Когда любой экземпляр кода принимает строку для обработки, он отмечает, что processed = 1, поэтому он не будет рассмотрен в других случаях.

Так что, когда я бегу 50 экземпляров этого кода, он становится тяжелым в базе данных MySQL (и у меня есть только 4 Гб оперативной памяти)

Из-за того, что я получаю статистику, как те:

Traffic: 

Received 15.8 MiB 
Sent 42.9 GiB  

ø per hour 

Received: 3 MiB 
Sent: 8.1 GiB 

Немного статистики из PHPMyAdmin:

enter image description here

Как оптимизировать это? Чтобы иметь возможность запускать этот код параллельно, но не перечислять все таблицы?

// EDIT:

Результаты создания таблицы являются:

CREATE TABLE queue ( userid INT (11) NOT NULL, queuenumber INT (11) NOT NULL AUTO_INCREMENT, processed TINYINT (1) NOT NULL, ПЕРВИЧНЫЙ КЛЮЧ (queuenumber), уникальный ключ queuenumber (queuenumber), уникальный ключ userid (userid) ) ENGINE = InnoDB AUTO_INCREMENT = 121617 DEFAULT CHARSET = latin1

+2

Пожалуйста, разместите полное сообщение 'CREATE TABLE', включая любые ключи. Кроме того, как часто вы попадаете в базу данных? Данные об использовании памяти, которые вы указали, не так высоки. –

+0

Как это медленно? Стол становится большим? У вас есть указатель на 'queue.queuenumber'? – Haneev

+3

Шаг 1. Не выбирайте *, если вам действительно не нужно каждое поле. –

ответ

2

Реализация очередей с СУБД является анти-модель: http://blog.engineyard.com/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you

Однако, если вы настаиваете, есть способы сделать это последовательно без условий гонки.

Сначала введите уведомление (за пределами MySQL), когда новая строка находится в очереди, поэтому вам не нужно запрашивать новые данные в быстром цикле - возможно, поэтому ваш трафик настолько высок. Я видел многоадресную рассылку UDP, используемую для этого, или сигналы UNIX.

Теперь проверьте таблицу использует InnoDB

SHOW CREATE TABLE `queue`; 

Если вам необходимо изменить его в InnoDB

ALTER TABLE `queue` ENGINE=InnoDB; 

Если у вас есть несколько потребителей обработки заданий обеспечить ваши блокировки гонки бесплатно; каждый раз, когда потребитель сталкивается с новым заданием, первое, что он должен попытаться сделать, это обновить его с помощью уникального идентификатора процесса.каждый потребитель должен выполнить обновление на столе, чтобы присвоить строку/задание на потребитель по ID

Вам нужно будет иметь столбец процесса на ваш столе

ALTER TABLE `queue` ADD `process` int unsigned default NULL; 

Добавить индекс, чтобы помочь вам выбрать строки эффективно

ALTER TABLE `queue` ADD KEY (`processed`,`process`); 

Теперь ваши потребители могут запустить следующие в коде

UPDATE `queue` SET process = ? WHERE process IS NULL AND processed = 0 LIMIT 1; 

Вы можете установить? быть pid или идентификатором потока потребителя. Вы можете определить, удалось ли обновить строку, либо проверив затронутые строки в ответе запроса (быстрее), либо попытайтесь получить данные о строках в любом случае - возможно, вы вернете 0 строк, что означает, что обновление ничего не сделало - другой потребитель получил работа.

SELECT * FROM `queue` WHERE process = ? AND processed = 0; 

Когда потребитель закончил с строки/работы можно просто установить переработанной 0 на этой строке (может быть, вы должны рассмотреть первичный ключ таблицы автоматического вкл вы можете точно решить одну строку)

ALTER TABLE `queue` ADD `id` bigint unsigned NOT NULL auto_increment FIRST, ADD primary key (`id`); 

Если ваши потребители врезаться по какой-либо причине вы можете сказать, что происходит, посмотрев на строку - если обработано = 0, но процесс был установлен, то что-то разбился при обработке этой строки.

+0

Обновление происходит до выбора «каждый раз, когда пользователь сталкивается с новым заданием, первое, что он должен попытаться сделать, это обновить его с помощью уникального идентификатора процесса» – abasterfield

+0

Пропущено это, хороший ответ. –

Смежные вопросы