Как лучше всего организовать хранение друзей и контактов в базе данных?

Привет! У меня есть приложение с базой данных MySQL, и я сталкиваюсь с вопросами относительно хранения списка контактов пользователей. Ниже описаны основные функции приложения:

- Пользователь A регистрируется на сайте и импортирует свою записную книжку.
- Если друг B из записной книжки тоже регистрируется в приложении, пользователю A приходит уведомление: "Твой контакт зарегистрировался в приложении! Скорее добавляй его в друзья".
- Пользователь A может отправить заявку в друзья пользователю B.

С организацией друзей все более-менее понятно. У меня есть таблица friendships, содержащая поля: id, date, userId, friendId, canWrite. При добавлении друга в эту таблицу создаются две записи — для пользователя A и для пользователя B.

Теперь у меня вопрос о хранении списка контактов в базе данных. Первоначально я подумал о создании таблицы contacts со следующими полями: id, date, userId, friendPhoneNumber. Однако меня беспокоят некоторые моменты:

1. Если 10,000 пользователей импортируют по 100-200 контактов, то количество записей в базе может превысить 1 миллион.
2. При таком количестве строк может возникнуть замедление обычных SELECT-запросов, хотя я планирую создать индексы на userId и friendPhoneNumber.

Преимущества такой структуры заключаются в простоте запросов, например, `SELECT userId FROM contacts WHERE phoneNumber = '...'`, что позволит быстро находить всех пользователей с определенным контактом.

Другой вариант — использование типа колонок 'массив' в PostgreSQL. Это решение выглядит многообещающе (например, хранить контакты как varchar[] в таблице пользователей), но меня беспокоит скорость выполнения выборок пользователей, у которых есть определенный контакт.

Есть ли другие оптимальные решения для данной ситуации? Я открыт к переходу на PostgreSQL или другие базы данных, если это поможет.
  • 10 сентября 2024 г. 12:43
Ответы на вопрос 2
Хранение контактов пользователей в базе данных требует взвешенного подхода для обеспечения организованности и производительности. Вот несколько рекомендаций по оптимизации хранения и работы с контактами в вашей системе.

### Основные идеи для хранения контактов

1. **Структура таблицы контактов**:
   Вы можете использовать следующую схему для таблицы контактов:

   ```sql
   CREATE TABLE contacts (
       id SERIAL PRIMARY KEY,
       userId INT NOT NULL,
       contactName VARCHAR(255), 
       contactPhoneNumber VARCHAR(20), 
       createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
       UNIQUE(userId, contactPhoneNumber)  -- Уникальность для одного пользователя
   );
   ```

   - Такое решение позволит избежать дублирования контактов для одного и того же пользователя, а также обеспечит быструю выборку по `userId` и `contactPhoneNumber`.

2. **Индексация**:
   Создание индексов на `userId` и `contactPhoneNumber` как раз поможет вам эффективно выполнять выборки. С учетом того, что у вас много пользователей, рекомендую следить за производительностью запросов и периодически оптимизировать индексы.

3. **Каскадные действия и связи**:
   Если вы планируете реализовать дополнительные действия (например, удаление контактов), подумайте о том, как реализовать каскадное удаление или управление связями между таблицами.

### Альтернативные решения

1. **Шардирование данных**:
   Если вы ожидаете, что количество пользователей и контактов будет расти, подумайте о шардировании данных. Это поможет распределить нагрузку и упростить обработку больших объемов данных.

2. **Сравнение с анонимизированными данными**:
   Вы можете хранить контакты в анонимизированном формате, например, хешировать номера телефонов. Это обеспечит дополнительный уровень конфиденциальности, но усложнит задачи поиска.

3. **Оценка перехода на PostgreSQL**:
   PostgreSQL поддерживает массивы, но использование массивов в качестве данных может усложнить выборку и обновление данных. Например, чтобы найти всех пользователей с определенным контактом, вам придется использовать сложные операции (например, `UNNEST`). Вместо этого лучше держать данные в нормализованной структуре, что улучшает читаемость и делает запросы более простыми.

4. **Использование NoSQL базы данных**:
   Если приложение предполагает высокую нагрузку, рассмотрите возможность использования NoSQL баз, таких как MongoDB, для хранения контактов. Это может увеличить скорость операций, особенно при больших объемах данных, однако усложнит выполнение сложных запросов.

5. **Кеширование**:
   Используйте кеширование для наиболее часто запрашиваемых данных. Например, Redis может использоваться для хранения временных данных о контактах, что позволит снизить нагрузку на базу данных.

### Заключение

Учитывая ваши текущие требования и рост данных, я рекомендую воспользоваться нормализованной схемой таблицы, как описано выше, с использованием индексов и регулярным мониторингом производительности. Постоянно оценивайте производительность системы, и если возникнут проблемы, можно будет проанализировать более сложные решения, такие как шардирование или использование NoSQL.
Первое что пришло в голову - таблица contacts
норм

1. 10.000 пользователей импортируют свои 100-200 контактов - в бд уже будет >1 млн записей
это мало

Если строк будет очень много, то будет ли тормозить обычный select? на userId и phoneNumber будут индексы
с большой вероятностью не будет, но обычно если возникает вопрос, собирают тестовый стенд и проверяют самостоятельно.
Похожие вопросы