В последнее время все чаще слышу упоминания про NoSQL и MongoDB в частности. Тема меня заинтересовала, но вот пока не могу найти интересующей меня информации, поэтому спрошу здесь — наверняка уже многие успели поэкспериментировать, а может и разработать серьезные высоконагруженные приложения в связке с MongoDB.
Заранее предупрежу, если где-то я ошибся в отношении MongoDB — я не специально. Просто я с ней еще даже не пытался работать, а лишь почитывал статьи на Хабре, да те примеры, что лежат на оф.сайте.
Сейчас я занимаюсь разработкой тизерной сети. Задача, на первый взгляд кажущаяся тривиальной, на деле выходит довольно хитровыделанной в плане организации структуры БД. Огромное кол-во связей, множество таблиц-посредников для связей М-М и т.д… Чем меня привлекла идея MongoDB, так это своим принципом построения связей. Вопрос №1:
действительно ли работа с МонгоБД при наличии кучи связей менее затратна в плане ресурсов? Ну, хотя бы на простейшем примере (буду писать на «псевдо SQL») — выборка из 2 таблиц, связанных отношением М-М через промежуточную таблицу:
table sites(
id int primary key auto_increment,
url varchar
)
table categories(
id int primary key auto_increment,
name varchar
)
table sites_categories(
site_id int,
category_id int
)
Задача вывести список сайтов и категорий, в которых он есть:
SELECT * FROM sites
while(SITE = mysql_result...)
{
//отображаем данные сайта
SELECT * FROM categories WHERE id IN (SELECT category_id FROM sites_categories WHERE site_id = SITE)
//в цикле отображаем категории
}
Также меня интересует, можно ли работать одновременно с MySQL и MongoDB? Вернее, насколько это будет правильно? Полностью переносить БД на Монго не хочется, лишь отдельные, особо-хитрые участки, нагрузка на которых выше, чем хочется.
Также читал, что в MongoDB можно беспроблемно хранить файлы — действительно ли это так и что же будет лучше — хранить по-старинке в специальной папке с подкаталогами по именам/ид пользователей, или использовать MongoDB? (допустим, при таком раскладе: пользователей около 1к, у каждого 40-50 небольших картинок. картинки отдаются в кол-ве примерно 100-150 в минуту.
P.S.: прошу прощения за возможные неточности в вопросах, излишнюю или недосказанную информацию о нуждах и текущем положении дел, разработка структур БД — не мое основное достоинство…
Извиняюсь за оффтоп, но в ваших примерах вроде SELECT * FROM categories WHERE id IN (SELECT category_id FROM sites_categories WHERE site_id = SITE)
JOIN принципиально не используется???
это псевдо-sql, я же написал :)
Просто с Join'ами я не очень хорошо до сих пор разбираюсь, если без манов под рукой, поэтому так и написал, чтобы просто суть донести :)
Вообще, имхо, связи многие-ко-многим не являются сильной стороной Mongo (да и других NoSQL БД, с которыми знаком). Наиболее эффективно они работают со встроенными объектами, то есть связями один-к-одному и односторонними один-ко-многим.
Mongo эффективен, когда один объект (или массив объектов) можно вложить в другой и первый без второго не имеет никакого смысла. Примеры — профиль в учётной записи, комменты к постам, адреса и телефоны в адресной книги. В таком случае связанные данные хранятся вместе и осуществляется, грубо говоря, одна операция поиска по идентификатору («первичному ключу») и получения объекта (с разной глубиной вложенности в зависимости от цели запроса) — эффективность можно сравнивать с денормализованной РСУБД. Если же используются ссылки («внешние ключи»), то таких операций нужно производить несколько — по сути от JOIN ничем не отличается. Хотя, конечно, можно денормализовать и Mongo базу или использовать для вашего примера в качестве «первичного ключа» категорий их название, а в качестве первичного ключа сайтов их урлы (тогда типичные задачи «вывод деталей сайта и названия его категорий» и «вывод деталей категории и урлы входящих в неё сайтов» будут осуществляться за одну операцию)
Для монго каждый сайт должен включать в себя есть category_id с перечислением категории. То есть, для nosql связь много-ко-многим реализуется хранением в одном из объектов полного перечисления отношений ко второму.
И запрос например получить все тизеры для Москвы где еще остались клики, к примеру больше 10 pastie.org/1226857
Относительно надежности и скорости, честно хз, еще не экспериментировал глобально, тут вам придется самостоятельно провести изыскания, одно могу сказать, скорость внедрения и расширения радует :)
Снова оффтопик:
Вообще я дорабатывал тизерную сеть одну… Там нет таргетинга но нормально отрабатывало около 90 млн показов тизеров в сутки (сейчас обороты спали примерно до 50 млн). Все это крутится на одном единственном довольно мощном сервере (и второй сервер — только картинки).
Там все данные о тизерах, забаненных айпишниках, ценой за показ/клик забираются из мемкеша. Если в мемкеше каких то данных почему-то нет (Eviction например или холодный старт), то только тогда забирается из БД и кладется сразу обратно в мемкеш. Статистика за последнюю минуту тоже кладется в мемкеш и раз в минуту данные из него собираются, обсчитываются и обобщенная статистика кладется в MySQL. Т.е. фактически для открутки тизеров БД вообще не трогается.
(До мемкеша вообще использовали файловую систему для этих данных — летало почти так же как на мемкеше)
Но вам может не подойти потому что не представляю толком как там можно таргетинг реализовать.
Метод его организации практически не изменяет полезности вашего комментария — просто локально хранятся данные диапазонов IP, а при выборке тизеров на показ добавляется +1 условие, чтобы IP клиента был в диапазоне кампании, из которой выбираются тизеры. Если интересно — могу в личке подробнее рассказать :)
По поводу идеи мемкеша — спасибо, планировалось перед запуском добавить работу с ним.