powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Работа с интервальными данными
3 сообщений из 3, страница 1 из 1
Работа с интервальными данными
    #35991119
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!
Вот такая задачка: Есть N устройств, с которых поступает информация в виде ID устройства, штампов времени начала и окончания, кода раздела (int), и некого значимого положительного значения (integer).
Все эти данные пишутся в таблицу
Код: plaintext
1.
2.
3.
4.
create table DEV_DATA(ID bigint not null primary key,
TS_START timestamp not null,
DEV_ID integer not null,
REV_ID integer not null,
ACTUAL_DATA integer not null);
Данные поступают с переменной интенсивностью, от 50 отчетов в минуту до 1 отсчета в три-четыре часа. По условиям ТЗ разрешена дискретизация штампов времени с точностью до минуты, поэтому решили округлять штампы времени до минуты и суммировать с предыдущими показаниями показаниями устройства этой же минуты. Работает, заказчик доволен. Но, выяснился один нюанс... Порядка 97% отчетов - короткие, т.е. штампы времени начала и окончания находятся в пределах одной-двух минут, что не принципиально для заказчика. Но есть еще 3% отчетов, которые имеют большую длительность - до получаса. Занести их в таблицу - не проблема, но пара нюансов остается. В текущей реализации таблицы теряем "скорость поступления" данных, ибо не хранится штамп завершения. Если добавим доп. столбец с штампом времени завершения, то:
- во-первых, в 97% случаев получим мало значимое поле;
- во-вторых, забьем таблицу "лишними" данными, что не есть хорошо при приросте таблицы в 100000 записей в сутки;
- в-третьих, отчетные запросы сильно усложняются.
Собственно, проблема такова: заказчик хочет видеть (в оперативном режиме) график скорости поступления данных за любой период (час, день, месяц) по устройству в целом и по разделам. В первоначальном варианте таблицы - это реализуется легко и красиво, но в ряде случаев не отражает реальной ситуации.
Во варианте доп. поля не очень понятно, как выбирать. Например, есть запись:
Код у-ва 34, штамп начала 21.01.09 13:16, штамп завершения 21.01.09 17:34, данные 945674.
Заказчик хочет график за 21.01.09 с 14:00 до 15:00. Простой
Код: plaintext
select * from DEV_DATA where DEV_ID=:dev_id and ((TS_START between :START_TS and :FINISH_TS) or (TS_FINISH between :START_TS and :FINISH_TS));
эту запись не зацепим. Можно, конечно, дописать конструкцию типа:
Код: plaintext
and (:START_TS between TS_START and TS_FINISH)or(:FINISH_TS between TS_START and TS_FINISH))
Но куча OR'ов с BETWEEN'ами явно росту производительности не будут способствовать.

Была еще идея преобразовывать "длинные" отчеты в список коротких "минутных" и хранить их в таком виде с соответствующим дроблением данных, но в таком варианте получается, что придется добавлять записи не в конец таблицы (по PK и штампу времени старта), а в середину, что потребует корректировки индексов. Что, тоже не очень хорошо... К тому же, не ясно, что делать, если, паче чаяния, заказчик захочет изменить интервал дискретизации в ту или иную сторону.

Может, сталкивался кто-то с реализацией таких задач?
...
Рейтинг: 0 / 0
Работа с интервальными данными
    #35991258
Kirill Razuvaev
Во варианте доп. поля не очень понятно, как выбирать. Например, есть запись:
Код у-ва 34, штамп начала 21.01.09 13:16, штамп завершения 21.01.09 17:34, данные 945674.
Заказчик хочет график за 21.01.09 с 14:00 до 15:00. Простой
Код: plaintext
1.
2.
select * from DEV_DATA 
where DEV_ID=:dev_id and 
((TS_START between :START_TS and :FINISH_TS) or (TS_FINISH between :START_TS and :FINISH_TS));
эту запись не зацепим. Можно, конечно, дописать конструкцию типа:
Код: plaintext
1.
and (:START_TS between TS_START and TS_FINISH)
or(:FINISH_TS between TS_START and TS_FINISH))
Но куча OR'ов с BETWEEN'ами явно росту производительности не будут способствовать.

Может, сталкивался кто-то с реализацией таких задач?
Вообще-то нормальная реализация. И потом, в запросе можно объединить условия:
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from DEV_DATA 
where DEV_ID=:dev_id and 
(
 ((TS_START between :START_TS and :FINISH_TS) or (TS_FINISH between :START_TS and :FINISH_TS))
or
 ((:START_TS between TS_START and TS_FINISH) or (:FINISH_TS between TS_START and TS_FINISH))
)
...
Рейтинг: 0 / 0
Работа с интервальными данными
    #35991349
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Три раза OR, четыре BETWEEN - представляю, как сервер обрадуется. Особенно, с учетом того, что это "оперативный запрос"... Плюс доп.поле в таблицу...
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Работа с интервальными данными
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]