Оптимизировать запрос для большой таблицы в базе данных (SQL) - PullRequest
1 голос
/ 28 апреля 2020

Я пытаюсь оптимизировать запрос sql для большой таблицы событий (10 миллионов + строк) для поиска по диапазону дат. У меня уже есть уникальный индекс для этой таблицы, который (крышка, сделал, измерение, дата). Запрос ниже пытается получить событие трех типов измерения (киловатты, ток и напряжение) для каждого 2-секундного интервала в столбце даты:

SELECT *, FLOOR(UNIX_TIMESTAMP(date)/2) AS timekey 
from events 
WHERE lid = 1 
  and did = 1
  and measurement IN ("Voltage") 
group by timekey
UNION
SELECT *, FLOOR(UNIX_TIMESTAMP(date)/2) AS timekey 
from events
WHERE lid = 1
  and did = 1
  and measurement IN ("Current") 
group by timekey
UNION
SELECT *, FLOOR(UNIX_TIMESTAMP(date)/2) AS timekey 
from events
WHERE lid = 1
  and did = 1
  and measurement IN ("Kilowatts") 
group by timekey

Это таблица, которую я пытаюсь найти.

=============================================================
id  |  lid   |   did   |   measurement  |  date 
=============================================================
1   |  1     |   1     |   Kilowatts    | 2020-04-27 00:00:00
=============================================================
2   |  1     |   1     |   Current      | 2020-04-27 00:00:00
=============================================================
3   |  1     |   1     |   Voltage      | 2020-04-27 00:00:00
=============================================================
4   |  1     |   1     |   Kilowatts    | 2020-04-27 00:00:01
=============================================================
5   |  1     |   1     |   Current      | 2020-04-27 00:00:01
=============================================================
6   |  1     |   1     |   Voltage      | 2020-04-27 00:00:01
=============================================================
7   |  1     |   1     |   Kilowatts    | 2020-04-27 00:00:02
=============================================================
8   |  1     |   1     |   Current      | 2020-04-27 00:00:02
=============================================================
9   |  1     |   1     |   Voltage      | 2020-04-27 00:00:02

Ожидаемый результат - получение всех данных, дата которых равна 2020-04-27 00: 00:00 и 2020-04-27 00:00:02. Приведенный выше запрос работает как положено. Но я использую UNION для просмотра различных измерений в таблице, и я считаю, что это может быть неоптимальный способ сделать это.

Может ли любой эксперт SQL помочь мне настроить запрос, который я должен увеличить производительность?

Ответы [ 3 ]

1 голос
/ 28 апреля 2020

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

Вы можете попробовать:

select *
from events
where 
    lid = 1 
    and did = 1 
    and measurement IN ('Voltage', 'Current')
    and extract(second from date) % 2 = 0

Это выберет записи, которые иметь четную вторую часть.

В качестве альтернативы, если у вас всегда есть одна запись каждую секунду, другой параметр - row_number() (для этого требуется MySQL 8.0):

select *
from (
    select 
        e.*, 
        row_number() over(partition by measurement order by date) rn
    from events
    where 
        lid = 1 
        and did = 1 
        and measurement IN ('Voltage', 'Current')
) t
where rn % 2 = 1

Это немного менее точный, чем предыдущий запрос.

0 голосов
/ 30 апреля 2020

В дополнение к приведенным выше предложениям, изменение PRIMARY KEY даст вам немного больше производительности:

PRIMARY KEY(lid, did, date, measurement)

и подброс id.

Предостережение, возможны икоты, если два чтения приходят в одно и то же «второе». Это может легко произойти, если одно чтение наступит сразу после тактов, а следующее - перед следующим тактом.

0 голосов
/ 28 апреля 2020

Ваш запрос фактически состоит из трех запросов, объединенных в один. К счастью, все они выбирают строки данных на основе похожих столбцов. Если вы хотите, чтобы этот запрос выполнялся быстро, вы можете добавить следующий индекс:

create index ix1 on events (lid, did, measurement);
...