Помогите со схемой базы данных на 50 + ГБ БД - PullRequest
0 голосов
/ 23 октября 2009

У меня есть задача хранить большой объем данных GPS и некоторую дополнительную информацию в базе данных и получать к ней доступ для отчетов и некоторых других нечастых задач.

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

Сообщение 1: DeviceId Lat Lon Speed ​​Course DIO1 ADC1
Сообщение 2: DeviceId Lat Course DIO2 IsAlarmOn
Сообщение 3: DeviceId Lat Lon Height Course DIO2 IsAlarmOn и т. Д. До 20-30 полей

Невозможно объединить количество полей - поставщики разных устройств, разные протоколы и т. Д. И еще одна головная боль - размер базы данных и необходимость поддержки как можно большего числа поставщиков БД (используется NHibernate).

Итак, я пришел к идее хранить сообщения таким образом:
Таблица1 - Треки
PK - TrackId
TrackStartTime
TrackEndTime
FirstMessageIndex (хранит MessageId)
LastMessageIndex (хранит MessageId)
DeviceId (не FK)

Таблица2 - Сообщения
PK - MessageId
TimeStamp
FirstDataIndex (хранит DataId)
LastDataIndex (хранит DataId)

Table3 - MessageData
PK - DataId
двойные данные
короткий DataType

Все индексы назначены с hilo. Настроил мои запросы так, чтобы Nhibernate мог быстро обрабатывать сообщения более 3000+ k сообщений (также используется кэширование). Я доволен игрой. Но я не знаю, как это будет работать при размере 50+ ГБ или 100+ ГБ.

Буду очень признателен за любые советы и подсказки по моей проблеме и дизайну хранилища в целом =)
Спасибо, Алексей
PS.Извините за мой английский =)

Ответы [ 3 ]

3 голосов
/ 23 октября 2009

В двух словах, ваше приложение, в частности, гетерогенная структура сообщений , полученных от устройств GPS, подталкивает ваш дизайн к структуре хранилища данных EAV (при этом сущность является сообщением Атрибут является «MessageData.DataType», а значение систематически удваивается.)

Схема трех таблиц, которую вы обрисовали в общих чертах в вопросе, однако, похоже, немного отличается от традиционной реализации EAV, в том смысле, что существует неявная последовательность для способа хранения MessageData, посредством которого все данные точки для данного сообщения последовательно нумеруются (DataId), и ссылка из сообщения на его точки данных будет управляться DataId в пределах диапазона.
Это плохая идея ! Многие проблемы с этим, примечательным является то, что это создает ненужное узкое место для вставки сообщений. Не удается начать вставку второго сообщения, пока не будут указаны все точки данных для предыдущего сообщения. Другая проблема заключается в том, что это затрудняет индексацию отношения между сообщением и точкой данных (базовая СУБД не будет эффективной в этом).
==> Предложение. Сделайте MessageId внешним ключом в таблице MessageData . (и, возможно, вообще удалите PK DataId из таблицы MessageData, просто для экономии места за счет необходимости использовать составной ключ для ссылки на конкретную запись в этой таблице, например, в целях обслуживания)

Еще одно предложение - хранить наиболее распространенные атрибуты (точки данных) на уровне таблицы сообщений . Например, Lat и Long, но, возможно, также Course или Some alarms и т. Д. Причиной правильности этой информации в сообщении является оптимизация запросов к данным (ограничение количества самостоятельных объединений, необходимых с помощью таблицы MessageData.

Поскольку таблицы «Сообщения» и «MessageData» могут не содержать часть сообщения, вы также можете переименовать последнюю таблицу «MessageDetail» или другое имя.

Наконец, может быть хорошей идеей будет разрешить значения данных, отличные от значений типа double . Я предполагаю, что некоторые предупреждения являются просто логическими и т. Д. Помимо разрешения принимать различные типы точек данных (скажем, короткие строки сообщений об ошибках ...), это также может дать вам возможность разделить точки данных по нескольким таблицам «подробностей»: одна для двойников, один для логических значений, один для строк и т. д. Этот способ усложняет схему в том смысле, что вам необходимо встроить некоторые из этих деталей в способ создания запросов, но он может обеспечить некоторый потенциал для производительности / масштабирования. прибыли.

0 голосов
/ 28 декабря 2009

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

Кроме того, вы можете создавать поля, которые содержат указанные (длина) данные, что означает, что вы можете сохранить место и улучшить производительность.

У меня есть один поставщик с известными значениями, поэтому я создал одну таблицу для этого. Эта таблица может быть легко разделена с помощью собственного механизма MS SQL Server.

Итак, моя самая простая ситуация позволяет мне написать одну хранимую процедуру для сохранения данных. Там нет NHibernate, только чистый ICommand.

Остальная часть приложения использует NHibernate.

0 голосов
/ 24 октября 2009

Я постараюсь описать, как это работает, теперь более подробно в ответе, потому что комментарии имеют фиксированную длину =) Вот последовательность получения:
1. Служба получает сообщения от MSMQ (количество сообщений может отличаться - используется пакетная рассылка 500 сообщений).
2. Затем уточняются различные идентификаторы устройств.
3. Для каждого идентификатора устройства используется изолированный кэш-память MS EntLib со структурой:
DeviceId -> Список, где DeviceId является ключом поиска.
4. Если у нас более 1k сообщений в кеше - запишите их в БД в одной последовательности и после записи «index» в таблицу поиска:
Индекс: ID
serial_id
index_start_datetime
index_end_datetime
index_first_dataid
index_last_dataid
5. Очищает кеш для этого DeviceId

Также я храню данные в парах: id data1 data2 type
например широта, скорость, adc1, adc2, dio1, dio2 и если нет связанного значения: значение 0

Я выбрал double, потому что я могу хранить в нем все типы данных, отправляемых устройствами. Строки не отправляются, но большинство из них в стиле csv, например 1,0,23,50,0000N30.00000,1,2,12,0,1,2 и т. Д. Даже данные тревоги и т. Д. Имеют одинаковый тип данных. Когда мне нужно получить некоторые данные, я просто нахожу индексы для данного окна даты и времени и DeviceId и получаю фактические данные, зная, когда они начинаются и заканчиваются. И нет сложных запросов. Просто 2 простых. Другой код интерпретирует это, используя некоторые «отображения» протокола. Спасибо за совет EAV. Я думаю, что это хорошо вписывается. Первая таблица Track предназначена для агрегации сообщений и быстрого получения их в алгоритме извлечения. Я описал пару строк ранее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...