Масштабируемая база данных MySQL для обмена почтовыми сообщениями

Предположим, у нас есть популярный сайт. Нам нужно реализовать почтовый обмен сообщениями между пользователями. Типичным решением является использование 2 таблиц:

Пользователи (user_id)

Сообщения (message_id, sender_id (ссылка на user_id), Receiver_id (ссылка на user_id), тема, тело ).

Этот метод имеет 2 существенных ограничения

  1. Все сообщения всех пользователей хранятся в одной таблице, что приводит к ее высокой нагрузке и снижению общей производительности базы данных.
  2. Когда кому-то нужно отправить сообщение нескольким пользователям одновременно, сообщение копируется (recipients_count) раз.

В другом решении используются 3 таблицы:

Пользователи(user_id)

Отправленные_сообщения(sent_id, sender_id (ссылка на user_id), тема, тело)

Received_messages(sent_id, Receiver_id (ссылка на user_id), тема, тело)

тема и тело полученных_сообщений копируются из соответствующих полей отправленных_сообщений.

Этот метод приводит к

  1. Денормализация базы данных путем копирования информации из одной таблицы в другую
  2. Пользователи могут фактически удалять отправленные/полученные сообщения, не удаляя их из получателей/отправителей.
  3. Сообщения занимают примерно в 2 раза больше места
  4. Каждая таблица загружена примерно в 2 раза меньше.

Итак, вопросы:

  1. Какой из рассмотренных дизайнов лучше подходит для высокой нагрузки и масштабируемости? (думаю это второй)
  2. Есть ли другой дизайн базы данных, который может справиться с высокой нагрузкой? Что это? Каковы ограничения?

Спасибо!

P.S. Я понимаю, что прежде чем перейти к этим проблемам с масштабируемостью, сайт должен быть очень успешным, но я хочу знать, что делать, если мне нужно.

ОБНОВЛЕНИЕ

В настоящее время для первых версий я буду использовать дизайн, предложенный Даниэлем Вассалло. Но если в дальнейшем все будет ок, дизайн будет изменен на второй. Спасибо Эверту за то, что развеял мои опасения по этому поводу.


person Sergii Vozniuk    schedule 10.02.2010    source источник


Ответы (2)


Возможно, вы захотите избежать многократного копирования тела сообщения в случае, если сообщение отправляется нескольким получателям. Вот еще один вариант, который вы можете рассмотреть:

  • пользователи (user_id)

  • сообщения (message_id, sender_id, тема, тело)

  • received_messages (message_id, user_id, address_mode, удалено)

Эта модель больше похожа на твиттер, чем на электронную почту, но у нее есть некоторые преимущества.

Правила таковы:

  • Сообщение может быть отправлено только одним пользователем, указанным в sender_id каждого сообщения.
  • Каждый получатель будет определен в таблице Received_messages. Поле address_mode может определить, было ли сообщение отправлено получателю напрямую, или как CC, или, может быть, как BCC. Это поле, очевидно, является необязательным.
  • Сообщения, удаленные получателями, будут помечены флажком удаления в таблице Received_messages.
  • Переадресованные сообщения и сообщения с ответами необходимо воссоздавать с новым идентификатором sender_id. Затем тело сообщения может быть изменено.

Вот некоторые из преимуществ:

  • Это занимает меньше места, чем два варианта, упомянутых в исходном вопросе, особенно если пользователи обычно отправляют сообщения нескольким получателям.
  • Более простое кэширование таблицы сообщений, поскольку сообщения никогда не дублируются.
  • Получатель, удаляющий сообщение, не удалит информацию о том, что сообщение было отправлено этому пользователю. Оно будет просто помечено как «удалено» в таблице Received_messages.
  • И вы также получаете нормализованную модель.

Для большинства приложений, если вы используете оптимистичный уровень изоляции с вышеуказанной моделью, у вас не должно быть проблем с производительностью, даже если вы ожидаете, что обмен сообщениями будет осуществляться со скоростью несколько сообщений в секунду. Если, с другой стороны, вы ожидаете сотни или тысячи сообщений в секунду, возможно, стоит рассмотреть другие варианты.

person Daniel Vassallo    schedule 10.02.2010
comment
Спасибо! Я тоже рассматривал эту конструкцию. На самом деле после публикации этого вопроса я (мысленно :)) изменил первый дизайн на Пользователи (user_id) Сообщения (message_id, sender_id, Receiver_id, message_content_id) Message_content (message_content_id, subject, body) Таким образом, оба эти дизайна лучше, чем первый (в занятое пространство и производительность стола). Может быть, постановка вопроса должна была быть примерно такой: лучше хранить все сообщения в одной таблице или копировать их в две? Насколько значительным будет влияние на производительность? - person Sergii Vozniuk; 10.02.2010

В целом размер базы данных не будет иметь большого значения. Скорость гораздо важнее.

Поэтому у меня был бы соблазн пойти по второму варианту. Как вы упомянули, это значительно упрощает такие вещи, как удаление сообщений, и я уверен, что это очень распространенный способ сделать это.

person Evert    schedule 10.02.2010