Хранение больших объемов данных в базе данных
В настоящее время я работаю над проектом домашней автоматизации, который предоставляет пользователю возможность просматривать потребление энергии в течение определенного периода времени. В настоящее время мы запрашиваем данные каждые 15 минут, и мы ожидаем около 2000 пользователей для нашего первого большого пилота.
Мой начальник просит нас хранить данные как минимум за полгода. Быстрая сумма приводит к оценкам около 35 миллионов записей. Хотя эти записи небольшие (около 500 байт каждая), я все еще задаюсь вопросом, является ли правильное решение хранить их в нашей базе данных (Postgres).
Есть ли у кого-нибудь хороший справочный материал и / или советуете, как обращаться с таким количеством информации?
6 ответов
На данный момент 35M записей по 0,5К каждая означает 37,5G данных. Это помещается в базу данных для вашего пилота, но вы должны также подумать о следующем шаге после пилота. Ваш начальник не будет счастлив, когда пилот добьется большого успеха, и вы скажете ему, что вы не сможете добавить 100 000 пользователей в систему в ближайшие месяцы, не изменив все заново. Более того, как насчет новой функции для VIP-пользователей, которая запрашивает данные каждую минуту...
Это сложная проблема, и выбор, который вы сделаете, ограничит развитие вашего программного обеспечения.
Для пилота, сделайте так, чтобы продукт был как можно более дешевым -> хорошо для базы данных. Но скажите вашему боссу, что вы не можете открыть такой сервис и что вам придется что-то менять, чтобы получить 10000 новых пользователей в неделю.
Одна вещь для следующего выпуска: иметь много хранилищ данных: одно для ваших пользовательских данных, которое часто обновляется, другое для вашей системы запросов / статистики,...
Вы можете посмотреть RRD для вашего следующего выпуска.
Также имейте в виду частоту обновления: 2000 пользователей обновляют данные каждые 15 минут, значит 2,2 обновления в секунду -> хорошо; 100 000 пользователей, обновляющих данные каждые 5 минут, означают 333,3 обновления в секунду. Я не уверен, что простая база данных может справиться с этим, а один сервер веб-службы определенно не может.
Мы часто используем таблицы, которые выглядят так. Очевидно, структурируйте свои индексы на основе использования (много ли вы читаете или пишете и т. Д.), И с самого начала подумайте о секционировании таблиц на основе некоторой высокоуровневой группировки данных.
Кроме того, вы можете реализовать идею архивирования, чтобы сохранить живую таблицу тонкой. Исторические записи никогда не затрагиваются или не публикуются, по моему мнению, обе таблицы не годятся для жизни.
Стоит отметить, что у нас есть таблицы с записями около 100 м, и мы не видим проблем с производительностью. Впоследствии многие из этих улучшений производительности могут быть выполнены без особых усилий, поэтому вы всегда можете начать с решения, основанного на здравом смысле, и настраиваться только тогда, когда производительность окажется низкой.
Прежде всего, я бы посоветовал вам сделать тест производительности - написать программу, которая генерирует тестовые записи, соответствующие количеству записей, которые вы увидите за полгода, вставьте их и проверьте результаты, чтобы убедиться, что время запроса удовлетворительное. Если нет, попробуйте выполнить индексацию в соответствии с другими ответами. Кстати, также стоит попробовать записать производительность, чтобы убедиться, что вы действительно можете вставить объем данных, которые вы генерируете, за 15 минут... 15 минут или меньше.
Проведение теста позволит избежать матери всех проблем - предположений:-)
Также подумайте о производственной производительности - у вашего пилота будет 2000 пользователей - будет ли ваша производственная среда иметь 4000 пользователей или 200000 пользователей в год или два?
Если мы говорим о действительно большой среде, вам нужно подумать о решении, которое позволит вам масштабировать, добавляя больше узлов, вместо того, чтобы полагаться на возможность всегда добавлять больше ЦП, диска и памяти на одну машину. Вы можете сделать это в своем приложении, отслеживая, на какой из нескольких машин баз данных размещается информация для конкретного пользователя, или вы можете использовать один из методов кластеризации Postgresql, или вы можете пойти совершенно другим путем - подход NoSQL, где вы полностью уходите от РСУБД и используете системы, построенные для горизонтального масштабирования.
Существует ряд таких систем. У меня есть только личный опыт Кассандры. Вы должны думать совершенно иначе по сравнению с тем, к чему вы привыкли в мире СУБД, что является сложной задачей - больше думать о том, как вы хотите получить доступ к данным, а не о том, как их хранить. Для вашего примера я думаю, что было бы целесообразно сохранить данные с идентификатором пользователя в качестве ключа, а затем добавить столбец с именем столбца, являющимся меткой времени, и значением столбца, являющимся вашими данными для этой метки времени. Затем вы можете запросить срезы этих столбцов, например, для отображения результатов в веб-интерфейсе. У Cassandra достаточно времени отклика для приложений с пользовательским интерфейсом.
Преимущество вложения времени в изучение и использование системы nosql заключается в том, что когда вам нужно больше места - вы просто добавляете новый узел. То же самое, если вам нужна большая производительность записи или большая производительность чтения.
С соответствующими индексами, чтобы избежать медленных запросов, я не ожидал бы, что какая-либо достойная СУБД будет бороться с такими наборами данных. Многие люди используют PostgreSQL для обработки гораздо большего количества данных.
Это то, для чего созданы базы данных:)
Вам не лучше не хранить отдельные образцы в течение всего периода? Возможно, вы могли бы реализовать какой-то механизм консолидации, который объединяет еженедельные / ежемесячные выборки в одну запись. И запустите указанную консолидацию по расписанию.
Ваше решение должно зависеть от типа запросов, которые необходимо выполнить в базе данных.
Есть много методов для решения этой проблемы. Вы получите производительность, только если дотронетесь до минимального количества записей. в вашем случае вы можете использовать следующие методы.
- Старайтесь хранить старые данные в отдельной таблице, здесь вы можете использовать разбиение таблиц или использовать другой подход, при котором вы можете хранить свои старые данные в файловой системе и обслуживать их непосредственно из вашего приложения без подключения к базе данных, таким образом, ваша база данных будет буть свободен. Я делаю это для одного из моих проектов, и у него уже есть более 50 ГБ данных, но он работает очень гладко.
- Попробуйте индексировать столбцы таблицы, но будьте осторожны, так как это повлияет на скорость вставки.
- Попробуйте пакетную обработку для вставки или выберите запросы. Вы можете решить эту проблему очень умно здесь. Пример: предположим, что вы получаете запрос на вставку записи в любую таблицу через каждую 1 секунду, затем вы создаете механизм, где вы обрабатываете этот запрос в пакет из 5 записей таким образом, что вы попадете в базу данных через 5 секунд, что намного лучше. Да, вы можете заставить пользователей ждать в течение 5 секунд, пока они не вставят свою запись, как в Gmail, где вы отправляете электронное письмо, и он просит вас подождать / обработать. для выбора вы можете периодически помещать свой набор результатов в файловую систему и предоставлять его непосредственно пользователю, не касаясь базы данных, как это делает большинство компаний, занимающихся данными фондового рынка.
- Вы также можете использовать некоторые ORM, такие как Hibernate. Они будут использовать некоторые методы кэширования для повышения скорости ваших данных.
Для любого дальнейшего запроса вы можете написать мне на ranjeet1985@gmail.com