Я проводил небольшое исследование того, как хранить друзей пользователя в базе данных, и создал свою таблицу на основе модели, полученной из этого ответа здесь
Человек также предложил настроить индексы на (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
?