Где или как хранить большие объемы данных (python + mysql)
думаю сделать таблицу, где буду считать общее кол-во за день - пока вижу только этот вариант.
1 ответов
Для таких случаев идеально подходит секционирование таблицы. Делаете одну большую таблицу, разбиваете на секции типа Range по дате. Период партицирования зависит от объема и логики дальнейших расчетов: идеально было бы 1 день - 1 секция, но можно разбить и по часу или еще как-то. Если секции все-равно большие, можно добавить субпартиции (подсекции) типа List по ID баннера.
В самой таблице никаких автоинкриментов, ключей, индексов, констрейнтов ("NOT NULL" и т.п.) делать не надо. Обеспечьте чтобы приложение, а не база занималась проверками данных. Тогда вставка записи будет происходить максимально быстро.
Теперь можно динамично лопатить большие объемы данных. Регулярно по крону или еще как-то должны добавляться новые партиции на завтра. Если будете делать субпартиции, при добавлении новых баннеров нужно оперативно менять шаблон партицирования, иначе будут фейлы вставки. Обратите внимание, новые субпартиции появятся только в новой партиции. В это время строки пишутся в сегоднешнею.
Данные, собранные в одной секции - вся история за день. По прошествии суток можно неспеша запустить запрос с каунтом и группировкой (тут очень помогут субпартиции - они работают лучше индекса). Обсчитать все что нужно, сохранить в другой, сводной таблице и затем alter table drop partition - через секунду от гигабайт данных не осталоь и следа.
бОльшая часть проектов в которых мне удалось поучаствовать хратит такую информацию в текстовых файлах. Потому что скорость добавления - очень важный параметр. Файлы обычно посуточные. В особо тяжелых случаях - почасовые. Далее некий скрипт на кроне периодически считает по этим логам обобщенную статистику а сами логи либо архивирует, либо удаляет.
А вот конкретно в проекте, над которым работаю в данное время, логи кликов пишутся в mysql таблицу. Объемы - сравнимые с Вашими. Таблица, естественно без всяких индексов. Иначе добавления неприлично нагрузят сервер.
Раз в неделю таблица дампится и суммируется с предыдущими данными в другую базу данных, на другую машину. Там уже рисуются индексы и по той таблице идет обсчет. Исходная таблица обрезается до нулевого размера, и цикл повторяется по-новой. не сказать, что это очень оптимальный способ, текстовый файл все же выгоднее. Но железо позволяет в данном конкретном случае выпендриться :) Дело в том, что по спецификации нам детальную инфу по кликам нужно хранит три года. Храним в отдельной базе на отдельной машине в таблицах по годам-месяцам. Там и обсчитываем, там и отчеты делаем.
Но по фен-шую все же лучше текстовые файлы. Во всех отношениях лучше.
Под большие объёмы таких несвязных данных (а просмотров планируется много, да?) я бы рекомендовал отказаться от реляционных БД и смотреть в сторону NOSQL. Тот же MongoDB покроет вашу нагрузку с полпинка:
- Резкие инсерты и апдейты.
- Асинхронные запросы по дефолту (вам самое то, ибо не сильно критично потерять пару просмотров из 100 тысяч).
- Кластеризация из коробки (если таки упрётесь в производительность одного сервера).
- MapReduce спасает при агрегировании показов по суткам.
Наверное лучше будет вообще отдельную БД под это дело сделать. Конечно для приложения будет дополнительной нагрузкой подключение еще к одной БД - но думаю это нивелируется при очень больших объемах. Дополнительные плюсы - при разрастании сайта базу со статистикой без проблем можно будет перенести на отдельный сервер.
Еще вариант - создавать новую таблицу в БД через определенные периоды времени (сами периоды высчитываем эмпирическим путем - когда размер таблицы приближается к ограничению по размеру ). Имена таблиц в этом случае привязываем к этим периодам, чтобы наше приложение смогло определить, откуда брать записи при получении статистики.
Ваш вариант с одной стороны прост - пишем только ID банера и инкрементим количество кликов/показов, и если такой статистики хватит то в принципе нормально. Только следует учесть - при таком количестве показов может возникнуть проблема с одновременным доступом к записи.
В одном проекте была схожая задача. Была решена так:
Подсчет показов / кликов ведется insert'ом в таблицу (mysql). Каждые 24 часа выполняется скрипт, который выбирает count показов и кликов из этой таблицы, группируя их по id баннера, и записывает из в другую таблицу. Скрипт может выбирать данные порционно, скажем, удаляя те записи, которые были обработаны, с лимитом в 10 записей (помните, что скрипт делает выборку с group by).