какой наиболее эффективный способ запрашивать все сообщения в приложении группового чата?

#sql #scaling

#sql #масштабирование

Вопрос:

я приведу пример, чтобы проиллюстрировать свой вопрос.

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

 ------------------- 
id | name |owner_id|
------------------- 
33 | code | 45
  

у вас есть таблица сообщений, в которой хранятся сообщения

 ------------------------------------- 
id | content | user_id | chat_room_id
------------------------------------- 
5  | "hello" | 41      | 33
2  | "hi"    | 43      | 33
  

у вас есть таблица users, в которой содержится информация о пользователях и о том, в каком групповом чате они участвуют:

 ------------------------------------- 
id | name | chat_room_id
------------------------------------- 
5  |"nick"| 33
2  |"mike"| 33
  
  1. это правильный способ настройки базы данных?
  2. без соединений или внешних ключей. какой наиболее эффективный способ загрузить все сообщения и пользовательские данные и представить их в форме, позволяющей создать пользовательский интерфейс, в котором пользовательские данные отображаются рядом с сообщением?

Мои решения:

если вы запросите базу данных сообщений и получите все сообщения, в которых идентификатор комнаты чата равен 33, вы получите массив, который выглядит так

 [
  {
   id : 5,
   user_id : 41,
   content : "hello"
  },
  {       
   id : 2,
   user_id : 43,
   content : "hi"
  }
]
  

как вы можете видеть, идентификаторы пользователей являются частью объекта message.

решение 1: (наивное): перебрать массив сообщений и запросить базу данных, используя идентификатор пользователя. это плохое решение, поскольку запрос к базе данных из цикла никогда не является хорошей идеей.

решение 2: (эффективное, но меньше данных для отправки в ответе): перебираем массив сообщений и создаем массив идентификаторов пользователей и используем его в запросе WHERE user_id IN , затем перебираем массив пользователей и создаем хэш-таблицу, используя идентификатор пользователя в качестве ключа, поскольку он уникален. во внешнем интерфейсе просто просмотрите массив сообщений и найдите пользователя.

это решение будет очень медленным, если у вас большое количество сообщений. будет ли он хорошо масштабироваться, поскольку он равен O (n).

решение 3: (эффективное, но больше данных для отправки в ответе): то же самое, что и раньше, но разница здесь заключается в добавлении свойств к объекту messages, в котором хранятся пользовательские данные. проблема с этим решением заключается в том, что у вас будут дублирующиеся данные, поскольку один пользователь может публиковать несколько сообщений.

это мои решения, которые я надеюсь услышать от вас.

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

Комментарии:

1. Клиент чата, скорее всего, уже знает общую информацию о пользователях в комнате. Предполагая, что вы не можете получать сообщения от пользователей, не участвующих в групповом обсуждении, клиент может просто сопоставить имя из списка участников? Честно говоря, вы не должны заботиться о преждевременной оптимизации этого. Сначала выберите то, что легко поддерживать, и оптимизируйте оттуда.

2. да, я понимаю, что вы говорите.

3. Что значит «без использования join «? Зачем хранить данные в базе данных, если вы не собираетесь использовать функциональность базы данных?

4. ну, сначала я подразумеваю под «суставами» наличие отношения «один ко многим» (один пользователь: много сообщений). в архитектуре микросервисов база данных пользователей и база данных сообщений принадлежат разным службам, поэтому невозможно иметь внешний ключ, который указывает на другую таблицу. обе таблицы должны запрашиваться независимо.