Как я могу оптимизировать эту операцию MySQL? - PullRequest
0 голосов
/ 28 июня 2019

У меня есть эта таблица - «использование продукта». Столбцы в этой таблице: id, rank, product_id, checked_at (отметка времени). Я пытаюсь добавить в эту таблицу еще один столбец (отметку времени) с именем last_inactive и задним числом заполнить этот столбец. Логика для этого 1) Найти create_at для ближайшей следующей записи для того же product_id (упорядочено по рангу) 2) Возьмите эту временную отметку и вычтите 1 секунду и используйте эту временную отметку, чтобы заполнить текущий столбец и продолжить 3) Если следующая строка не существует, используйте now () в качестве значения для last_inactive

Я попробовал следующее, чтобы получить желаемый результат

SELECT *,
        coalesce(
date_sub(
(SELECT checked_at
              FROM product_usage p2
              WHERE p2.rank > p.rank
              and p.product_id=p2.product_id
              group by id, product_id, created_at
              ORDER BY product_id, rank ASC
              LIMIT 1 OFFSET 0),
INTERVAL 1 second),
now()
)
as valid_until
FROM product_usage p
where p.product_id = '1111111';

Этот запрос работает для этого конкретного product_id, но он занимает около 2-3 секунд для product_id, и существует около 20k различных product_ids, для которых я хочу, чтобы это работало. Что я могу сделать, чтобы сделать это быстрее?

1 Ответ

0 голосов
/ 28 июня 2019

Агрегирование в подзапросе не требуется. Итак, попробуйте это:

SELECT pu.*,
       coalesce(date_sub( (SELECT pu2.checked_at
                           FROM product_usage pu2
                           WHERE pu2.rank > pu.rank AND
                                 pu2.product_id = pu.product_id
                           ORDER BY pu2.rank ASC
                           LIMIT 1 OFFSET 0
                          ), INTERVAL 1 second
                        ), now() ) as valid_until
FROM product_usage pu
WHERE pu.product_id = 1111111;  -- looks like a number so removed the single quotes

Тогда для этого вам нужен индекс на product_usage(product_id, rank, created_at).

Конечно, в MySQL 8+ вы просто используете lead().

...