Организация большого количества значений с метками времени в БД (sql / nosql) - PullRequest
2 голосов
/ 09 ноября 2010

У меня есть устройство, которое я опрашиваю для множества различных полей, каждые х миллисекунд устройство возвращает список идентификаторов и значений, которые мне нужно сохранить с отметкой времени в своего рода БД.

Пользователи системы должны иметь возможность запрашивать у этой БД исторические журналы для создания графиков или запрашивать последнюю отметку времени для каждого значения.

Простой подход заключается в определении таблицы MySQL с

id,value_id,timestamp,value

и пусть пользователи выбирают

Select value form t where value_id=x order by timestamp desc limit 1

и просто добавьте туда все с индексом timestamp и id, но мой вопрос, каков наилучший подход к производительности / размеру для проектирования схемы? или используя nosql? Кто-нибудь может прокомментировать возможные компромиссы дизайна. Будет ли такой дизайн масштабироваться с миллионами записей?

Ответы [ 2 ]

1 голос
/ 09 ноября 2010

У вас есть выбор

  • индексы (составные; охватывают value_id, timestamp и value или некоторую их комбинацию): вам следует тестировать производительность с разными индексами; составной и не составной, также имейте в виду, что существует довольно много различных способов получить «максимум на группу» (поиск, особенно версия mysql с переменными)

  • триггеры - вы можете использовать триггеры для поддержания максимальных значений строки в другой таблице (лучшая производительность при дальнейшем выборе; это избыточно и может храниться в памяти)

  • ленивая статистика / триггеры, так как ваша база данных обновляется довольно часто, вы можете сохранять циклы, если вы периодически обновляете статистику (если вы можете позволить статистике быть y секунд и если вы опрашиваете 1000 / x раз в секунду , тогда вы потенциально сохраняете y * 100 / x потенциальных обновлений, и это может быть заметно, особенно с точки зрения масштабируемости)

Вышесказанное верно, если вы ищете последний бит производительности, если не упростите его.

1 голос
/ 09 ноября 2010

Когда вы говорите «... или запрашиваете последнюю метку времени для каждого значения», вы это имели в виду?

    select max(timestamp) from T where value = ?

Если у вас есть миллионы записей, и вы имели в виду вышеприведенное (то есть значение указано в предложении WHERE отдельно), тогда вам понадобится индекс для столбца значений, в противном случае вам придется составлять полную таблицу сканирования. Но если в запросах ВСЕГДА будет иметь столбец [timestamp] в предложении WHERE, вам не нужен индекс для столбца [value], если есть индекс для временной метки.

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

  select * from T where timestamp > x and timestamp < y

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

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

EDIT:

Добавление некоторых дополнительных замечаний после вашего разъяснения.

Мне интересно, как вы узнаете идентификатор? Возможно ли [id] код продукта?

Один простой индекс по идентификатору может не очень хорошо масштабироваться, если не много разных кодов продуктов, т. Е. Если это индекс с низким количеством элементов. Перебалансировка деревьев может замедлить пакетные вставки, которые происходят каждые x миллисекунд. Составной индекс (id, timestamp) будет лучше, чем простой индекс.

Если вам редко нужно сортировать несколько продуктов, но чаще всего выбираете на основе одного кода продукта, то нетрадиционная СУБД, использующая разреженную таблицу с хешированным ключом, а не b-дерево, может быть очень жизнеспособной даже превосходная альтернатива для вас. В такой базе данных все записи для данного ключа будут физически найдены на одном и том же наборе смежных «страниц»; алгоритм хэширования смотрит на ключ и возвращает номер страницы, где будет найдена запись. Нет необходимости перебалансировать индекс, так как индекс отсутствует, и поэтому вы полностью избегаете связанных с этим проблем масштабирования.

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

ДАЙТЕ ДРУГОЕ РЕДАКТИРОВАНИЕ, ПОЧЕМУ САЙТ НЕ ПОЗВОЛЯЕТ МЕНЯ ДОБАВИТЬ ДРУГОЙ ОТВЕТ

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

Update latest
set value = x
where id = ?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...