Оптимизация запроса для получения всей строки, где одно поле является максимальным для группы - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть таблица со схемой вроде, скажем,

EventTime   DATETIME(6),
EventType   VARCHAR(20),
Number1     INT,
Number2     INT,
Number3     INT,
...

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

SELECT * FROM table WHERE EventTime >= time1 and EventTime <= time2;

, тогда он сможет вернуть соответствующие строки почти мгновенно.

Из строк в этом временном окнеЯ хочу извлечь именно те, где Number1 является наибольшим для любой строки с этим EventType.Другими словами, я хочу сделать что-то эквивалентное этому запросу:

SELECT * FROM
  (SELECT EventType, MAX(Number1) as max_Number1
   FROM table
   WHERE EventTime >= time1 AND EventTime <= time2
   GROUP BY EventType) AS a
  LEFT JOIN
  (SELECT * FROM table
   WHERE EventTime >= time1 AND EventTime <= time2) AS b
  ON a.EventType = b.EventType AND a.max_Number1 = b.Number1)

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

SELECT EventType, MAX(Number1) as max_Number1
FROM table
WHERE EventTime >= time1 AND EventTime <= time2
GROUP BY EventType;

и

SELECT * FROM table
WHERE EventTime >= time1 AND EventTime <= time2;

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

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

Вопросы:

  1. Почему это занимает так много времени?Что делает движок базы данных?
  2. Есть ли способ написать этот запрос таким образом, чтобы он выполнялся разумно?
  3. Если нет, могу ли я написать его как хранимую процедурукаким-то образом?

Сложность: Поскольку в этой таблице десятки миллиардов строк, было бы очень дорого добавить к ней какие-либо дополнительные индексы.

1 Ответ

0 голосов
/ 20 сентября 2018

Вы на самом деле уже достаточно близки к хорошему запросу.Ваш главный недостаток - это, скорее всего, СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ при выборе всего из table за определенный период времени.Попробуйте следующее:

SELECT * FROM
table b
INNER JOIN (
    SELECT EventType, MAX(Number1) as max_Number1
    FROM table
    WHERE EventTime >= time1 AND EventTime <= time2
    GROUP BY EventType
) AS a
ON a.EventType = b.EventType
AND a.max_Number1 = b.Number1
WHERE b.EventTime >= time1 AND b.EventTime <= time2

В идеале это должно сопровождаться индексом (EventType,EventTime).Пожалуйста, укажите SHOW CREATE TABLE table в вашем вопросе, чтобы мы могли видеть, какие у вас есть индексы.Возможно, мы сможем настроить существующий или помочь вам удалить ненужные, чтобы разрешить добавление этого нового индекса.

Отказ от ответственности: мой опыт в основном исключительно в MySQL и InnoDB, но я думаю, что это все равно должно быть полезнодля MariaDB и MyISAM.

...