Задавайте вопросы, мы ответим
Вы не зашли.
Требуется совет опытного специалиста в организации базы данных личных сообщений. Задача кажется простейшей, но их очень много (уже порядка 80 млн) и работают они под большой нагрузкой (до 1 тыс запросов в сек).
Сейчас всё организовано в три таблицы, с использованием партицирования.
-- Входящие. Используется партицирование по pm_user_id - пользователю, который получает сообщение. Партиций на самом деле больше.
Отредактированно al420 (04.01.2011 13:50:16)
Неактивен
Насколько я понимаю, Вы не удаляете строки (чтобы обеспечить хитрую сортировку).
Пусть у человека есть 1000 входящих сообщений. Он видит первые 20. Это сообщения,
которые пришли год назад? Или я что-то не понимаю в этой схеме?
Можете использовать, например, MERGE для объединения живой и архивной табличек.
Ну и триггер, который бы перекладывал данные. Учтите, что перекладывание означает
удаление строки, что автоматически сломает вашу хитрую сортировку.
Я бы не закладывался на недокументированные особенности хранилищ. Кажется, InnoDB
с нормально организованными индексами, должен держать такую нагрузку. Ну и, если
будете переписывать, заложите шардирование сразу — все равно понадобится вдаль-
нейшем.
Неактивен
Всё верно строки не удаляются, просто выставляется флаг удаления. Это позволяет пользователю восстановить сообщение в течение некоторого времени. И ещё, это позволяет нумеровать сообщения для каждого пользователя отдельно. Например, я у себя удаляю не 123546547ое сообщение (это реальный `pm_id` в базе), а всего-лишь 34ое. А 35го "нету", я его раньше удалил, оно лежит в базе и считается но не показывается. Есть 36ое, и.т.д. ВКонтакте реализована такая фишка. Благодаря этому хранение сообщений одного пользователя можно организовать как угодно, на сколько угодно таблиц, а порядковые номера сообщений останутся прежними.
Он видит первые 20. Это сообщения, которые пришли год назад? Или я что-то не понимаю в этой схеме?
Нет, первые 20 которые он видит - это последние 20 которые пришли. LIMIT в запросе тоже нету, запрашиваются все ID-шники сообщений этого пользователя, нумеруются по порядку c учётом удалённых, массив реверсируется и новые оказываются в начале, потом к тем ID-шникам которые пришлись на страницу - подтягиваем тему и текст сообщений из `pm_content`.
Вот, теперь вроде полностью расписал )
Можно и реально удалять строки. Приходится, чтобы было меньше записей. Удаляются сообщения, у которых во входящих и исходящих стоит флаг удаления. Но тогда после удаления требуется делать OPTIMIZE TABLE и потом ещё ALTER TABLE ... ORDER BY, чтобы не падала недокументированная сортировка
Интересно, а как практически реализовано в том же Контакте, есть идеи?
Отредактированно al420 (04.01.2011 14:40:20)
Неактивен
То есть вы вытаскиваете всегда все записи? А если их станет очень очень много?
У вконтакта есть шардирование. У них большой датацентр, в котором крутится
большое количество машин, которые этим занимаются. Наверняка, есть и собст-
венное хранилище данных, но про это не знаю точно. У facebook есть.
Я бы на Вашем месте попробовал ORDER BY + LIMIT. Ну и шардирование, разу-
меется.
Неактивен
Да, вытаскиваю все. Очень много - уже стало. Вот и пишу
В этом решении мне нравилась возможность быстрой выборки, я был очень ограничен в технических ресурсах. Один быстрый селект с использованием индекса и только из одной партиции.
Теперь, видимо, придётся лепить всё снова с одну таблицу, использовать ORDER BY + LIMIT, а старые сообщения (например, которым больше месяца) - перекладывать в архивную таблицу по ночам. Или не старые, а когда их больше 40 (не вошли в первые 2 страницы). Но в этом случае придется подгружать архив, если пользователь удалит все новые...
Спасибо за советы, попробую построить на этих принципах.
Неактивен
Если разумно организовать шардирование, то архивные таблицы не понадобятся.
Ну и на InnoDB посмотрите, не нужно будет делать сто тысяч разделов, чтобы
сэмулировать строчную блокировку
Неактивен
решение с myisam, соритировкой и архивированием красивое, но послушайте еще одного человека: шардинг, партиции по необходимости, innodb, свежий mysql или innodb plugin. ну и если будет где потестить - handler socket.
Неактивен