Как масштабировать таблицу двунаправленных отношений? - PullRequest
0 голосов
/ 06 мая 2020

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

Человек также предложил настроить индексы на (UserIDLink1, UserIDLink2) и наоборот (UserIDLink2, UserIDLink1). Это двунаправленная связь, также отмеченная в ответе

(A - друг B, если B - друг A)

Я новичок в базах данных но я сделал эти индексы в Postgresql с типом btree, и я выбираю всех пользователей, которым это нравится:

SELECT u.*
   FROM users u
   INNER JOIN friends f ON u.username = f.username_link1 or u.username = f.username_link2
WHERE f.username_link1 = 'user27' or f.username_link2 = 'user27';

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

В любом случае это не кажется эффективным и не выглядит хорошо масштабируемым. Если у меня n = 10 000 пользователей, крайним случаем здесь будет (n ^ 2) записей, если каждый пользователь дружит с каждым пользователем. Маловероятно, но если бы у меня было 1 000 000 пользователей, это все равно было бы большим количеством записей в одной таблице для каждого двунаправленного отношения.

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

Возможно, я ошибаюсь, но это похоже на будущую катастрофу.

Вот мои схемы

CREATE TABLE users(
    id              TEXT            PRIMARY KEY NOT NULL,
    username        VARCHAR(15)     NOT NULL UNIQUE,
    first_name      VARCHAR(255)    NOT NULL,
    avatar_url      TEXT            NOT NULL,
);
CREATE TABLE friends(
    username_link1  VARCHAR(15)  NOT NULL REFERENCES users(username) ON DELETE CASCADE,
    username_link2  VARCHAR(15)  NOT NULL REFERENCES users(username) ON DELETE CASCADE,
    PRIMARY KEY (username_link1,username_link2)
);
CREATE INDEX index_link1 ON friends 
(
    // also created the vice versa of this
    user_id_link2 DESC,
    user_id_link1 DESC
);

Можно ли разложить эту таблицу на несколько дисков?
Есть ли лучший способ оптимизировать эту таблицу?
Было бы лучше просто создать таблица для каждого пользователя, поэтому я могу использовать простой SELECT * FROM 6762_friends?

...