Я развиваю дружеские отношения в MySQL, где дружеские отношения взаимны. Если A является другом B, то B является другом A. Если один из пользователей завершает дружбу, связь прекращается. Я хочу узнать, какой путь лучше.
У меня есть работающая система;
user
-----------
userid p.k
name
friends
-------
userid
friendid
primary key (`userid`,`friendid`),
key `friendid` (`friendid`)
1 2
2 5
1 3
To get all of my friends;
SELECT u.name, f.friendid , IF(f.userid = $userid, f.friendid, f.userid) friendid
FROM friends f
inner join user u ON ( u.userid = IF(f.userid = $userid, f.friendid, f.userid))
WHERE ( f.userid = '$userid' or f.friendid = '$userid' )
Этот запрос работает хорошо. Может быть, я могу добавить UNION
. Запрос является более сложным, чем приведенный ниже, и таблица содержит вдвое меньше записей, чем приведенная ниже.
Другой способ - сохранить отношения в отдельных строках;
1 2
2 1
2 5
5 2
1 3
3 1
SELECT u.name, f.friendid
FROM friends f inner join user u ON ( u.userid = f.friendid )
WHERE f.userid = '$userid'
Этот запрос прост, хотя таблица занимает вдвое больше места.
Моя забота предполагая, что есть миллионы пользователей; какой путь будет работать быстрее?
Каковы преимущества и недостатки обоих способов?
Что я должен иметь в виду или изменить для этих способов? И с какими проблемами я могу столкнуться в обоих направлениях?
источник
Ответы:
Первое, что бросается в глаза - это настройка индекса
friends
.У вас есть это на данный момент:
При перекрестной проверке взаимной дружбы это может потребовать небольших затрат, поскольку идентификатор пользователя может быть получен из таблицы при обходе
friendid
индекса. Возможно, вы могли бы индексировать следующим образом:Это может устранить любую необходимость доступа к таблице и поиска только по индексу.
Теперь, с точки зрения запросов, они оба могут улучшиться с новым уникальным индексом. Создание уникального индекса также устраняет необходимость вставить
(A,B)
и(B,A)
в таблицу , так(A,B)
и(B,A)
будет индекс в любом случае. Таким образом, второй запрос не должен был бы пролистывать таблицу, чтобы увидеть, является ли кто-то другом другого, потому что другой человек инициировал дружбу. Таким образом, если дружба нарушается только одним человеком, не бывает односторонних дружеских отношений, которые были бы односторонними (в наши дни это похоже на жизнь, не так ли?)Ваш первый запрос выглядит так, как будто бы он получил больше пользы от уникального индекса. Даже с миллионами строк поиск друзей с использованием только индексов позволит избежать прикосновения к таблице. Тем не менее, поскольку вы не представили запрос UNION, я бы порекомендовал запрос UNION:
Это позволит вам увидеть, кто является друзьями каждого пользователя
Чтобы увидеть все дружеские отношения, запустите это:
Во-первых, вот несколько примеров данных:
Давайте посмотрим на все отношения
Давайте рассмотрим все 5 идентификаторов пользователей и посмотрим, правильно ли показаны отношения
Все они выглядят правильно для меня.
Теперь давайте воспользуемся вашим вторым запросом, чтобы увидеть, соответствует ли он ...
Почему не совпадают? Это потому, что я не загружал
(B,A)
для каждого(A,B)
. Позвольте мне загрузить(B,A)
отношения и повторить ваш второй запрос.Они все еще не совпадают. Это потому, что ваш второй запрос проверяет только одну сторону.
Давайте проверим ваш первый запрос по каждому значению только с (A, B) и не с (B, A):
Ваш первый работает хорошо. Я уверен, что он выигрывает от уникального индекса, как я уже говорил ранее, но ИМХО, я думаю, UNION проще. С чем уникальным индексом, это будет шесть из полутора десятков других с точки зрения исполнения и вывода.
Вы должны сравнить свой первый запрос с моим предложением UNION и посмотреть.
Это был хороший вопрос, который вы задали сегодня. +1 за твой вопрос.
источник
friendid
,userid
), и теперь результаты около .00794 Это так быстро, как только можно? Глядя на результаты, думаете ли вы, что первый способ лучше (по одной строке для каждого отношения)? Потому что это вдвое меньше места, чем второе, и результаты примерно одинаковы с текущими настройками.WHERE
,GROUP BY
иORDER BY
положения приводят данные считываются только из индексов. Вот несколько хороших ссылок, которые оправдывают использование уникальных и первичных ключей в качестве покрывающих индексов: 1) peter-zaitsev.livejournal.com/6949.html , 2) mysqlperformanceblog.com/2006/11/23/… , 3) ronaldbradford .com / blog / tag /