Как оптимизировать медленный MySQL запрос - PullRequest
0 голосов
/ 08 октября 2018

У меня следующий запрос MySQL, выполнение которого занимает много времени:

SELECT `market`.`name` AS `Markets`, count(*) * `clicks`.`cost` AS `Rev`
FROM `clicks`
INNER JOIN markets ON `clicks`.`market_id`= `markets`.`id`
WHERE clicks.created_date = `date1`
GROUP BY `markets`.`id`
ORDER BY `Rev` DESC

Изначально это было очень медленно, но позже я удалил избыточную функцию даты.Тем не менее, это занимает много времени, чтобы выполнить.Есть ли какое-нибудь решение для этого?

Объяснение запроса: я выбираю названия рынков из одной таблицы, а количество строк умножается на стоимость из другой таблицы.Идентификатор рынков определяется в первой таблице «клики», и я получаю названия рынков из таблицы «рынки».и далее я группирую рынки по их идентификатору и заказываю через Rev по убыванию

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Ваш запрос использует частичную группу MySQL с помощью функции .Вы группируете по рынку, но у вас есть случайный столбец clicks.cost, который не содержится в агрегате.Вы получите неверные результаты независимо от того, насколько быстро выполняется ваш запрос.

Вы можете изменить свой запрос следующим образом:

SELECT market.name AS Markets, subqry.Rev FROM (
    SELECT market_id, SUM(cost) AS Rev
    FROM clicks
    WHERE created_date = 'some date'
    GROUP BY market_id
) AS subqry
INNER JOIN markets ON subqry.market_id = markets.id
ORDER BY Rev DESC

После того, как вы убедились, что результаты верны, создайтеследующий индекс:

CREATE INDEX ix_clicks ON clicks (created_date, market_id, cost)
0 голосов
/ 08 октября 2018

Предположительно, вы намереваетесь:

SELECT m.name AS Markets, SUM(c.cost) AS `Rev`
FROM clicks c INNER JOIN
     markets m
     ON c.market_id = m.id
WHERE c.created_date = ?
GROUP BY m.name
ORDER BY Rev DESC;

Это не влияет на производительность.Однако индекс на clicks(created_date, market_id, cost) может дать вам желаемую производительность.

Если это не сработает, попробуйте следующее:

SELECT m.name AS Markets,
       (SELECT SUM(c.cost)
        FROM clicks c
        WHERE c.market_id = m.id AND c.created_date = ?
       ) AS `Rev`
FROM markets m
ORDER BY Rev DESC;

Это удалит внешнюю GROUP BY,который может быть большой прирост производительности.Для этого индекс должен немного отличаться, clicks(market_id, created_date, cost).

0 голосов
/ 08 октября 2018

Я знаю, что это не прямой ответ на вопрос, и Вы можете, если хотите, отказаться от меня (я понимаю человеческую природу, проявляя ненависть к альтернативным мыслителям).

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

К сожалению, это данные временных рядов.

Это будет расти и будет стоить вам потери производительности.

Для краткосрочный запуск добавление индексов может решить Ваш вопрос.

Но в долгосрочной перспективе , где появится много рынков, клики будут ~ 1 миллион в день «обходной путь индекса» - это не очень хорошее решение .

A) Если вы сделаете поле даты индекса, вы начнете медленную вставку.Потому что каждый раз он будет выполнять процедуры обновления индекса в фоновом режиме.

B) Если вы разберетесь с таблицей, через некоторое время будет трудно управлять, поскольку нехорошо иметь сотни разделов, и однажды придет делос очень «неудобной» задачей для текущей структуры данных, которая приведет к переосмыслению схем таблиц.

Решение состоит в том, чтобы переосмыслить Вашу логику:

  1. Используйте Kafka и вставьте в нее данные своего клика.
  2. Вставьте данные в таблицу clicks (таблица должнане имеют индексов для быстрой вставки).
  3. Создайте работника, который будет получать данные о кликах от Кафки, делать математику и создавать сводку по рынкам за день, неделю, месяц, год и т. д. Создавая таблицы:clicks_by_markets, clicks_by_markets_yearly, clicks_by_markets_weekly, clicks_by_markets_daily

Другое решение (без Кафки):

  1. Есть таблица clicks_raw для размещения данных запроса безобработка.
  2. Создание сценария, который будет планироваться каждые 10 минут, и обработка clicks_raw таблиц и заполнение таблиц, таких как: clicks_by_markets, clicks_by_markets_yearly, clicks_by_markets_weekly, clicks_by_markets_daily
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...