Допустим есть сайт, на котором пользователи регистрируются и пишут статьи в свой блог. Каждую статью можно оценить лайком и написать комментарий. Один инстанс MySQL хранит все статьи, лайки и комментарии к статьям 50 000 пользователей. Меня настигла мысль, что если блог заведет какая-то очень известная личность, и она напишет 500 статей, каждая их которых соберет 500 000 лайков, то в таблице будет 250 000 000 записей. А если он продолжит писать статьи, то рано или поздно наступит момент Х, когда сервер будет не справляться. Можете подсказать решение данной проблемы? Надо как-то сделать так, чтобы можно было просто подключать дополнительные инстансы и приложение автоматически знало где искать нужную информацию. Я прекрасно понимаю что решение этой задачи невозможно быстро расписать на этом проекте, но я потратил на поиск решения этой проблемы около недели, но так ничего и не придумал. Буду благодарен за любые подсказки.
По ночам просыпаетесь в холодном поту от мысли что сервер СУБД не справится с нагрузкой?
Есть различные решения, начиная от медитации и психотерапевтических сеансов.
А если серьезно, то есть два пути: первый это тернистый путь к познаниям самостоятельно, методом проб и ошибок. Второй - это просто купить сервис для интеграции на веб-сайте.
Сайта у нас ещё нет.
Базы данных нет.
Статей нет.
Известной личности нет.
Офигиллиарда лайков нет.
Но зато полные штаны беспокойства, А ВДРУГ БАЗА НЕ СПРАВИЦА!!!
В порядке конструктива.
Купи себе пару хороших книжек, а лучше пойди на нормальные курсы, которые от Авито, не помню, как они называются. Потом пойди поработать в нормальную контору, где можно на практике разобраться, что такое база данных и с какого конца к ней подходят. Не в смысле нагрузки, а чтобы и мысли не возникало про дичь типа таблиц вида likes_for_userid_847192.
И годков через 5 можешь начинать задумываться о вопросе, "что будет если в базе будет 1 000 000 000 0000 00000 000000!!!111адинадин записей".
Вряд ли есть какое-то чудо-решение в масштабируемости системы. Из довольно банальных советов: правильно спроектировать БД под большие нагрузки, добавив необходимые индексы. Но все равно наступит момент, когда нагрузка будет слишком большой и тогда будут исчерпаны доступные соединения к СУБД, появятся какие блокировки, таймауты, крэши и прочая радость. Что даже dev ops не спасут от "сервер временно недоступен".
В облаках можно в некоторой степени автоматически масштабировать вычислительные ресурсы, но так можно внезапно разориться из-за атаки какого-то бота.
Во первых, с чего вы взяли что сервер не будет справляться?
Во вторых шардинг дает только линейную оптимизацию нагрузки, т.е. позволяет распределить нагрузку на несколько серверов.
Скорее всего вы просто пишите код, который делает бессмысленные вычисления на каждый чих, вместо сохранения результата. Например вместо подсчета лайков с помощью count на каждый показ странички, считайте лайки увеличивая и уменьшая значение поля у поста.
Сложную аналитику же проводите оффлайн сторонними средствами, ибо sql базы для этого не подходят.
Счетчики лайков и комментариев (да и любые другие) я именно так и планировал делать. Дело в другом. Дело в том что со временем одна таблица может собрать в себе 1 000 000 000 записей, и вот тогда будут проблемы с выборкой по уникальном индексу (или не будет? Я никогда не работал с таким объемом данных). Например есть уникальная, отдельная таблица для каждого автора блога, которая хранит в себе записи о том, кто и какие записи лайкнул (она должна быть, потому что без нее пользователь может сколько угодно ставить лайки и будет невозможно отобразить то, какие записи пользователь уже лайкнул). Структура такая:
название таблицы: likes_for_userid_847192
колонки: id, liked_by_user_id, post_id
индекс: UNIQUE INDEX (liked_by_user_id, post_id)
Выборка происходит элементарно:
SELECT id FROM likes_for_userid_847192 WHERE liked_by_user_id = x AND post_id = y
По идее это элементарный select, и на обычном сайте никаких проблем бы не было. Но когда число записей в таблице может неожидано вырасти до огромных размеров, поведение становится непредсказуемым. Это меня и пугает.
Если мне не изменяет память, то даже у ВКонтакте есть лимит на количество лайков к записи. Лично видел несколько раз как больше определенного числа (какого именно - не помню) лайки не ставились и выдавалась непонятная ошибка. Возможно они специально ограничили это для того чтобы не было таких огромных таблиц.
Миллионы записей для выборок по индексу не являются проблемами, на запись и чтение там везде логарифмы и даже константная трудоемкости.
НО! могут возникнуть проблемы с обслуживанием больших таблиц, это извечная проблема всех баз данных и sql тут ничем не выделяется, особенно если вам нужно все операции проводить налету - например добавление или редактирование полей
p.s. еще раз, напоминаю, любые данные, которые сложно вытаскивать и понадобится читать часто - записывайте/кешируйте в специальные поля, можно триггером на изменения.
Вы должны разделять данные аналитики и данные, необходимые для работы сайта!
Мало того, часто можно допустить некоторый лаг между появлением данных и изменения поведения сайта на их основе, например какая то аналитика, которую вы считаете оффлайн, например каждый час, может дополнять какие то списки, в т.ч. кто меня лайкал, кого я лайкал и прочее (кстати эти списки проблем с производительностью НЕ СОЗДАДУТ еще раз там примитивный запрос)
И еще, на практике ни один нормальный человек не будет листать в интерфейсе миллионы страниц, так зачем такие делать и предоставлять интерфейс? Десяток и уже большая часть пользователей никогда дальше не пойдут. Это значит что - если кеширование данных создают проблемы - кешируйте только часть, на которую обратят внимание большинство, остальным отдавайте некушированное.
И еще, кешировать можно данные в момент первого обращения (или когда источник данных обновился), это усложняет структуру кеша но автоматизирует процесс оптимизации его создания.
rPman, Именно это и нужно. Поэтому я и задал этот вопрос. Надо найти какой-то способ, чтобы можно было разделить данные на максимально возможное число таблиц, но при этом приложение должно их легко находить. Спасибо за ответ. Буду думать дальше...
rPman, Можно же правда написать скрипт, который будет выкачивать редко просматриваемые данные на какой-нибудь отдельный сервер, а на "рабочем" оставить только часто просматриваемые (например последние 200 публикаций). Остальные N публикаций просматривают очень редко, а значит и кэш можно не подключать, так?