Нет, VIEW динамическая вещь, работает она на тех же объемах.
Вы искренне ошибаетесь...
;)
Не буду разводит теорию - сразу к практике перейдём...
Сделаем такую view (с лишней табличкой и сортировкой)
CREATE VIEW ev (id,ts,msg,val,quality,nam,description) AS SELECT m.MessageId, m.Timestamp, m.Text, t.Value,t.Quality,v.Name,v.Description
FROM messages_data m
JOIN trends_data t ON t.ID=m.MessageID AND m.timestamp=t.timestamp
JOIN variables_data v ON v.ID=m.MessageID
ORDER BY m.MessageID, m.Timestamp
Исходная база
SELECT COUNT(*) FROM messages_data;
10 894
SELECT COUNT(*) FROM trends_data;
694 256
смотрим план запроса
EXPLAIN ANALYZE
SELECT * FROM ev
WHERE id=142 AND ts BETWEEN '2021-12-01' AND '2022-01-18'
-> Nested loop inner join (cost=1049.73 rows=50) (actual time=0.533..4929.417 rows=9228 loops=1)
-> Filter: ((m.GroupID = <cache>(-(2))) and (m.MessageID = 142) and (m.`Timestamp` between '2021-12-01' and '2022-01-18')) (cost=1006.89 rows=50) (actual time=0.496..1570.360 rows=9387 loops=1)
-> Index range scan on m using PRIMARY (cost=1006.89 rows=4991) (actual time=0.096..1543.277 rows=10767 loops=1)
-> Single-row index lookup on t using PRIMARY (ID=142, Timestamp=m.`Timestamp`) (cost=0.76 rows=1) (actual time=0.357..0.357 rows=1 loops=9387)
Добавим данных в тренд
SELECT COUNT(*) FROM messages_data;
10 894
SELECT COUNT(*) FROM trends_data;
5 554 208
План не изменился...
EXPLAIN ANALYZE
SELECT * FROM ev
WHERE id=142 AND ts BETWEEN '2021-12-01' AND '2022-01-18'
-> Nested loop inner join (cost=1392.52 rows=499) (actual time=0.411..73.427 rows=9228 loops=1)
-> Filter: ((m.MessageID = 142) and (m.`Timestamp` between '2021-12-01' and '2022-01-18')) (cost=1000.38 rows=499) (actual time=0.380..27.775 rows=9387 loops=1)
-> Index range scan on m using PRIMARY (cost=1000.38 rows=4991) (actual time=0.105..11.896 rows=10767 loops=1)
-> Single-row index lookup on t using PRIMARY (ID=142, Timestamp=m.`Timestamp`) (cost=0.69 rows=1) (actual time=0.004..0.005 rows=1 loops=9387)
и теперь БЕЗ фильтра
EXPLAIN ANALYZE
SELECT * FROM ev
-> Nested loop inner join (cost=16118.27 rows=9982) (actual time=49.160..95.380 rows=9228 loops=1)
-> Nested loop inner join (cost=8275.40 rows=9982) (actual time=49.120..60.000 rows=9389 loops=1)
-> Sort: m.MessageID, m.`Timestamp` (cost=1038.45 rows=9982) (actual time=33.688..37.755 rows=10894 loops=1)
-> Table scan on m (cost=1038.45 rows=9982) (actual time=0.098..8.186 rows=10894 loops=1)
-> Single-row index lookup on v using PRIMARY (ID=m.MessageID) (cost=0.63 rows=1) (actual time=0.002..0.002 rows=1 loops=10894)
-> Single-row index lookup on t using PRIMARY (ID=m.MessageID, Timestamp=m.`Timestamp`) (cost=0.69 rows=1) (actual time=0.003..0.003 rows=1 loops=9389)
Т.е. выборка идёт по таблице messages_data. А потом по первичному ключу ищутся значения в таблице трендов.
Это ускоряет поиск.
Проверьте. Должно ускорить.
Но ключевым моментом здесь является объем таблицы архивов и сообщений. Строить отчет по таблице из нескольких тысяч строк существенно быстрее, чем из нескольких миллионов.
Это зависит только от того, будут ли использоваться индексы для поиска данных, или нет.
Если в запросах Вы планируете делать выборку без использования столбцов ID и Timestamp (по ним строится кластерный индекс), то размер таблицы трендов будет иметь значение (чем больше строк, тем медленнее выборка).
Если в запросе на выборку данные будут выбираться по ID и Timestamp (пример ниже), то количество строк в таблице трендов не имеет значения. Например, в таблице на 10 миллионов записей такая выборка будет очень быстрой. Скада именно так и работает, выбирая данные по индексируемым столбцам (иначе просмотр трендов был бы невозможен после роста таблицы трендов). В этом смысл индексов. Все остальные способы решения описанные в этой теме будут хуже.
SELECT * FROM `trends_data`
WHERE (`id` = 1) AND (`timestamp` >= '2021-01-13 10:50:00.000') AND (`timestamp` <= '2021-01-13 11:00:00.000')
Все верно. Но анализ данных часто включает в себя и значение переменной.
При использовании индексов дополнительные условия будут слабо влиять на производительность, т.к. сначала СУБД сделает выборку данных по индексам, а затем в полученной (малой) выборке будет искать нужные значения обычным перебором. Т.е. такой поиск тоже будет быстрым (если за искомый период по искомому ID данных не слишком много):
SELECT * FROM `trends_data`
WHERE (`id` = 1) AND (`timestamp` >= '2021-01-13 10:50:00.000') AND (`timestamp` <= '2021-01-13 11:00:00.000') AND (`value` = 5)
Если ничего не подходит, то нужно рассматривать варианты без использования стандартных таблиц. Лучшим по производительности было бы создание собственной таблицы в БД и заполнение её из скады готовыми данными с нужной структурой через RunSQL. Затем выборка в отчет как описано здесь (https://simple-scada.com/help/report/rep-user-data.html).
Чтобы сделать такое представление корректным, в таблице сообщений должен присутствовать ID параметра, по которому формируется сообщение.
Это полностью исключено, мы никогда не будем добавлять в стандартные таблицы колонки, которые нужны малому числу пользователей скады. Т.к. для 99% остальных пользователей это будут бесполезные колонки, которые просто съедят лишнее место на жестком диске и ухудшат производительность БД и скорость вставки данных или выборки из скады.