2015-03-20 5 views
0

Я реализовал очередность заданий в PHP & MySQL (который работает с несколькими сценариями, работающими параллельно), имея два запроса: первый обновляет строки в таблице с использованием значения идентификатора обновления, затем второй извлекает строки с этим значением , Эти два запроса выполняются внутри транзакции, чтобы предотвратить параллельное выполнение других сценариев извлечения тех же строк.Выбор строк и их обновление в одном запросе?

Первый запрос выглядит следующим образом:

UPDATE products p 
SET p.update_id = '550b8d7f3ba477.82670719', p.date_update_started = UTC_TIMESTAMP() 
WHERE p.id IN 
(
    SELECT p2.id 
    FROM 
    (
     SELECT p3.id 
     FROM products p3 
     WHERE p3.date_update_started < UTC_TIMESTAMP() - INTERVAL 1 HOUR # only allow the product processed if not selected for processing recently 
        AND p3.updated = 1 
     ORDER BY p3.some_date ASC 
    ) p2 
) 
LIMIT 100 

Затем второй запрос будет просто получить строки с ID обновления.

Вышеприведенный запрос занимает 0,4 секунды для выполнения на столе со 100 тыс. Строк. Производительность беспокоит меня, потому что таблица будет расти до десятков или сотен миллионов строк с течением времени.

Можно ли каким-либо образом изменить этот запрос, чтобы сделать его более эффективным?

РЕДАКТИРОВАТЬ: Механизм хранения - InnoDB, а таблица имеет 22 индекса.

+0

Является ли дата_update_started индексированной? Более медленное, чем ожидалось, время может также быть временем, которое требуется для обновления индексов, которые изменяются при обновлении. – Bob

+0

@Bob Да, и есть также указатель на 'date_update_started, updated'. Последнее - то, что MySQL использует в соответствии с EXPLAIN. – Nate

ответ

2

Будет ли это работать не так?

UPDATE products 
SET update_id = '550b8d7f3ba477.82670719', 
    date_update_started = UTC_TIMESTAMP() 
WHERE date_update_started < UTC_TIMESTAMP() - INTERVAL 1 HOUR 
    AND updated = 1 
ORDER BY some_date 
LIMIT 100 
+0

I * думаю * он делает то же. Теперь, когда я думаю об этом, причина, по которой я использовал уродливую структуру в моем запросе, состоит в том, что у меня был оператор GROUP BY в самом внутреннем подзапросе SELECT. Перезапуск запроса к вашему методу сокращает время выполнения от 0,4 секунды до 0,3 секунды. Лучше, но я все еще путаюсь, почему это так долго. – Nate