У меня есть социальная сеть, похожая на myspace, но я использую PHP и mysql, я искал лучший способ показать только опубликованные бюллетени пользователей fronm themself и от пользователей, с которыми они подружились.
Это включает в себя 3 таблицы
friend_friend = в этой таблице хранятся записи о том, кто есть кто friend_bulletins = это хранит бюллетени friend_reg_user = это основная пользовательская таблица со всеми пользовательскими данными, такими как имя и фото URL
Я опубликую схему таблиц бюллетеней и друзей ниже, я буду публиковать поля, важные для таблицы пользователя.
- Структура таблицы для таблицы friend_bulletin
CREATE TABLE IF NOT EXISTS `friend_bulletin` (
`auto_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(10) NOT NULL DEFAULT '0',
`bulletin` text NOT NULL,
`subject` varchar(255) NOT NULL DEFAULT '',
`color` varchar(6) NOT NULL DEFAULT '000000',
`submit_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`status` enum('Active','In Active') NOT NULL DEFAULT 'Active',
`spam` enum('0','1') NOT NULL DEFAULT '1',
PRIMARY KEY (`auto_id`),
KEY `user_id` (`user_id`),
KEY `submit_date` (`submit_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=245144 ;
- Структура таблицы для таблицы friend_friend
CREATE TABLE IF NOT EXISTS `friend_friend` (
`autoid` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(10) DEFAULT NULL,
`friendid` int(10) DEFAULT NULL,
`status` enum('1','0','3') NOT NULL DEFAULT '0',
`submit_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`alert_message` enum('yes','no') NOT NULL DEFAULT 'yes',
PRIMARY KEY (`autoid`),
KEY `userid` (`userid`),
KEY `friendid` (`friendid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2657259 ;
поля таблицы friend_reg_user, которые будут использоваться auto_id = это идентификационный номер пользователя disp_name = это имя пользователя pic_url = это путь к уменьшенному изображению.
//1 Старый метод использует подзаголовок
SELECT auto_id, user_id, bulletin, subject, color, fb.submit_date, spam
FROM friend_bulletin AS fb
WHERE (user_id IN (SELECT userid FROM friend_friend WHERE friendid = $MY_ID AND status =1) OR user_id = $MY_ID)
ORDER BY auto_id
//Другой старый метод, который я использовал для учетных записей с небольшим количеством друзей, потому что этот использует другой запрос который вернет строку всех друзей в этом формате $str_friend_ids = "1,2,3,4,5,6,7,8"
select auto_id,subject,submit_date,user_id,color,spam
from friend_bulletin
where user_id=$MY_ID or user_id in ($str_friend_ids)
order by auto_id DESC
Я знаю, что это плохо для производительности, поскольку мой сайт становится действительно большим, поэтому я экспериментировал с JOINS
Я верю, что это все, что мне нужно, кроме того, что его нужно модифицировать, чтобы также получать бюллетени, опубликованные мной, когда я добавляю это в часть WHERE, которая, кажется, разбивает его и возвращает несколько результатов для каждого опубликованного бюллетеня, я думаю, потому что это пытается возвратите результаты, что я friedn, а затем я пытаюсь считать себя другом, и это не работает хорошо.
Мое главное в этом целом сообщении, хотя я открыт для мнений о наилучшем способе выполнения этой задачи, многие крупные социальные сети имеют схожую функцию, которая возвращает список предметов, отправленных только вашими друзьями. Должны быть и другие более быстрые способы???? Я продолжаю читать, что JOINS не очень хороши для производительности, но как еще я могу это сделать? Имейте в виду, что я использую индексы и имею выделенный сервер базы данных, но моя база данных велика, нет никакого способа обойти это.
SELECT fb.auto_id, fb.user_id, fb.bulletin, fb.subject, fb.color, fb.submit_date, fru.disp_name, fru.pic_url
FROM friend_bulletin AS fb
LEFT JOIN friend_friend AS ff ON fb.user_id = ff.userid
LEFT JOIN friend_reg_user AS fru ON fb.user_id = fru.auto_id
WHERE (
ff.friendid =1
AND ff.status =1
)
LIMIT 0 , 30
Прежде всего, вы можете попытаться разбить базу данных, чтобы получить доступ к таблице с необходимыми первичными строками. Перемещайте строки, которые реже используются в другой таблице.
JOINs могут влиять на производительность, но из того, что я видел, подзапросы не лучше. Попробуйте рефакторинг вашего запроса, чтобы вы не вытаскивали все эти данные одновременно. Также кажется, что некоторые из этих запросов могут запускаться один раз в другом месте вашего приложения, и эти результаты сохраняются в переменных или кэшированных.
Например, вы можете кэшировать массив друзей, которые подключены для каждого пользователя, и просто ссылаться на них при запуске запроса и обновлять кеш только при добавлении/удалении нового друга.
Это также зависит от структуры ваших систем и архитектуры вашего кода. Ваша бутылочная nneck может не полностью находиться в db.