Возможность перепроектирования базы данных: какой дизайн таблицы использовать для сбора данных с этого датчика?


13

Фон

У меня есть сеть из примерно 2000 датчиков, каждый из которых имеет около 100 точек данных, которые мы собираем с 10-минутными интервалами. Эти точки данных обычно являются значениями типа int, но некоторые являются строками и числами с плавающей точкой. Эти данные должны храниться в течение 90 дней, больше, если это возможно, и все еще эффективно.

Дизайн базы данных

Когда мне изначально было поручено выполнение этого проекта, я написал приложение на C #, в котором файлы для каждого датчика были разделены запятыми. В то время было не так много, когда кто-то хотел посмотреть на тренды, мы открывали CSV-файл в Excel и отображали его по мере необходимости.

Все росло, и мы переключились на базу данных MySQL. Я создал таблицу для каждого датчика (да, я знаю, много таблиц!); это работало хорошо, но у него есть некоторые ограничения. С таким количеством таблиц, очевидно, невозможно написать запрос, который будет искать данные среди всех датчиков при поиске определенного значения.

В следующей версии я переключился на Microsoft SQL Server Express и поместил все данные датчиков в одну большую таблицу. Это также работает и позволяет нам выполнять запросы для поиска значений среди всех представляющих интерес датчиков. Однако я столкнулся с ограничением в 10 ГБ для версии Express и решил переключиться обратно на MySQL, а не инвестировать в SQL Server Standard.

Вопрос

Я доволен производительностью и масштабируемостью MySQL, но не уверен, что лучше придерживаться подхода «все данные в одной таблице». Кажется, 10 ГБ в одной таблице требуют другого дизайна. Я должен отметить, что необходимость запроса данных для построения графиков все еще существует, и я обеспокоен тем, что будут проблемы с производительностью для запроса, который отображает график, например, данные о температуре для одного датчика в течение полных 90 дней. (Другими словами, график должен быть чем-то, что можно быстро создать, не дожидаясь, пока SQL рассортирует кучу данных, просто чтобы изолировать интересующий датчик.)

Должен ли я каким-то образом разделить эту таблицу, чтобы повысить производительность? Или такой большой стол не является чем-то необычным?

У меня есть индексы для столбцов Sensor ID и Timestamp, которые в значительной степени определяют границы для любого запроса. (т.е. получить данные для датчика X от времени A до времени B).

Я прочитал немного о шардинге и разбиении, но не считаю, что они уместны в этом случае.


Редактировать:

На основании комментариев и ответов, некоторая дополнительная информация может быть полезна:

Не неопределенное хранение: в настоящее время я не храню данные за последние 90 дней. Ежедневно я запускаю запрос, который удаляет данные старше 90 дней. Если это станет важным в будущем, я буду хранить больше, но пока этого достаточно. Это помогает контролировать размер и высокую производительность.

Тип двигателя: оригинальная реализация MySQL использовала MyISAM. При создании таблиц на этот раз для новой реализации (одна таблица данных вместо многих) они по умолчанию использовали InnoDB. Я не верю, что у меня есть требование для одного или другого.

Нормализация: Есть, конечно, другие таблицы, кроме таблицы сбора данных. В этих таблицах поддержки хранятся такие данные, как информация о сети для датчиков, информация о входе в систему для пользователей и т. Д. Нормализировать особо нечего (насколько я знаю). Причина, по которой таблица данных имеет так много столбцов, состоит в том, что у каждого датчика столько переменных. (Несколько температур, уровень освещенности, давление воздуха и т. Д.) Нормализация для меня означает, что нет избыточных данных или повторяющихся групп. (По крайней мере, для 1NF.) Для данного датчика для хранения всех значений в определенное время требуется одна строка данных, и там нет взаимосвязей 1: N (что я вижу).

Я мог бы функционально разбить таблицу, сделав (например) все значения температуры в одной таблице, а все значения давления воздуха - в другой. Хотя это может повысить эффективность для тех, кто делает запрос только по температуре, мне все равно придется вставлять все данные одновременно. Тем не менее, повышение эффективности может быть полезным для операций SELECT. Очевидно, что лучше разбить таблицу по вертикали, исходя из того, как часто пользователи запрашивают данные. Возможно, это все, что я должен сделать. Я полагаю, что, задавая свой вопрос, я ищу подтверждение того, что это стоило бы.


Изменить 2:

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

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

По этой причине я утверждал, что около 100 точек данных будут собираться и храниться, даже если значение сомнительно. Но при обычном повседневном использовании пользователи обычно проверяют, возможно, дюжину этих параметров. Если пользователь интересуется определенной географической областью, он может (используя программное обеспечение) генерировать графики или электронные таблицы данных для, возможно, нескольких десятков датчиков. Нередко можно увидеть 30-дневный график с двумя или тремя линиями графика, показывающими такие вещи, как температура, давление воздуха и уровень освещенности. Выполнение этого запустит запрос, подобный следующему:

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(В исходной версии MySQL, где у каждого датчика была своя собственная таблица, будут выдаваться три отдельных запроса, но результаты объединяются в программном обеспечении для создания графика.)

Поскольку dataтаблица содержит так много строк (~ 10 миллионов), несмотря на наличие индексов idи data_timestamp, производительность заметно хуже, чем в сценарии с несколькими таблицами (4500 строк возвращаются за 9 секунд, а в этом примере - менее одной секунды). Возможность определить, какие датчики соответствуют определенным критериям, в схеме с несколькими таблицами практически равна нулю, и, следовательно, причина перехода к одной таблице.

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

Данные отбрасываются через 90 дней. Это могло быть заархивировано, но это не в настоящее время требование.

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


Чтобы получить правильный ответ на этот вопрос , вам, вероятно, следует подробнее рассказать о том, как на самом деле используются данные. Вы опережаете кривую по глубине предоставленной вами информации, но, возможно, задаете свой вопрос не с того угла.
Марк Стори-Смит

Хороший вопрос, @Mark, я также подробно остановлюсь на этом. Я старался не задавать слишком длинный вопрос, потому что это могло бы ошеломить.
Джелтон

Ответы:


5

Вы должны подумать о разделении таблицы по серьезной причине.

Все индексы, которые у вас есть в гигантской таблице, даже один индекс, могут генерировать большую нагрузку на ЦП и дисковый ввод-вывод только для выполнения обслуживания индексов при выполнении операций INSERT, UPDATE и DELETE.

Я написал предыдущую статью 7 октября 2011 года о том, почему разделение таблиц может помочь. Вот одна выдержка из моего прошлого поста:

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

Вы можете прочитать весь мой пост позже на этом.

Чтобы перейти прямо к погоне, вам нужно исследовать и выяснить, какие данные редко используются в вашей таблице на 10 ГБ. Эти данные должны быть помещены в архивную таблицу, которая легко доступна, если вам нужны специальные запросы для исторического характера. Перенос этого архива из 10 ГБ, за которым следует OPTIMIZE TABLEтаблица 10 ГБ, может привести к созданию рабочего набора, который быстрее запускает команды SELECT, INSERT, UPDATE и DELETE. Даже DDL будет работать быстрее на рабочем наборе 2 ГБ, чем на 10 ГБ.

ОБНОВЛЕНИЕ 2012-02-24 16:19 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Два момента для рассмотрения

  1. Из вашего комментария кажется, что вам может понадобиться нормализация.
  2. Возможно, вам потребуется перенести все данные старше 90 дней в таблицу архива, но при этом все равно получить доступ к архиву и рабочему набору одновременно. Если ваши данные все MyISAM, я рекомендую использовать механизм хранения MERGE. Сначала вы создаете карту таблицы MERGE, которая объединяет таблицу MyISAM рабочего набора и таблицу MyISAM архива. Вы будете хранить данные менее 91 дня в одной таблице MyISAM и переносить любые данные старше 90 дней в архив. Вы бы запросили только карту таблицы MERGE.

Вот два сообщения о том, как его использовать:

Вот дополнительный пост, который я сделал на столах с большим количеством столбцов

Слишком много столбцов в MySQL


Есть столбцы, которые нужны реже, но все датчики получают примерно одинаковый процент внимания. Таким образом, я могу представить, что разделение таблицы по вертикали было бы выгодно. Например, таблица из 20 столбцов (часто используется) и таблица из 80 столбцов (используется редко). Я не уверен, что это то же самое, что разделение.
Джелтон

Спасибо за редактирование. Я прочитал ваш пост о "Слишком много столбцов в MySQL". Я отредактирую свой вопрос с некоторыми дополнительными пунктами, которые могут быть полезны.
Джелтон

5

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

Является ли 90 дней обычным количеством времени, для которого вы создаете график? Если это так, у вас может быть две таблицы: основная таблица данных датчика, в которой хранятся данные от 90 (или чуть больше, если вы хотите немного провисать) дней назад до сегодняшнего дня, и все, что старше этого, помещается в архивную таблицу. Это может помочь уменьшить размер таблицы, из которой начинаются отчеты, и, надеюсь, большая часть ваших 10 ГБ данных будет в архивной таблице, а не в основной таблице. Задание архивирования может быть запланировано на ночь.

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


Хранить что-либо за последние 90 дней на этом этапе не нужно, но было бы неплохо. Я согласен, что лучше всего хранить в «архивной» таблице. Графики и анализ данных варьируются от нескольких часов до 90 дней. Большинство графических запросов использует только данные за последнюю неделю или около того, но 90-дневные графики являются общими. Наша фирма (пока) не запрашивала более длинные отчеты.
Джелтон

@JYelton: у вас может быть столько уровней в этом подходе, сколько вы хотите. Самая последняя таблица может быть только с сегодняшнего дня. Следующая таблица может быть с сегодняшнего дня до 2 недель назад. Следующая таблица может быть с сегодняшнего дня до 90 дней назад. Последний стол мог ВСЕ.
FrustratedWithFormsDesigner

Если я вас правильно понимаю, вы говорите, чтобы повторить таблицу, но с разными периодами времени. Поэтому, если кто-то запросит 7-дневный отчет, будет использована таблица, которая уходит только на неделю назад. Если они затем расширятся до 8 дней, будет ли использоваться следующая по величине таблица (например, 30-дневная)? Это, безусловно, повысило бы скорость запросов с более короткой продолжительностью, но за счет затрат на хранение (дешево) и логики программирования для работы с многоуровневыми таблицами (не так дешево).
Джелтон

@Джелтон: Да, я думаю, вы все правильно поняли. Если диапазоны периодов времени запроса являются стандартными (сегодня - 1 день, сегодня - 7 дней, сегодня - 30 дней, сегодня - 90 дней), то я не думаю, что это будет слишком сложно, так как вы всегда будете знать, какую таблицу хит. Если временные диапазоны могут иметь различную длину, где начало диапазона может не совпадать с текущей датой, то вы правы, логика для реализации усложнится и запросы, которые для перекрестных таблиц могут дорого обойтись с операциями UNION над несколькими таблицами.
FrustratedWithFormsDesigner
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.