Индексы, join и сортировка

Grapefruit Lips

Новичок
Здравствуйте,

есть таблицы: *friends* (кто с кем дружит) и *posts* - сообщения.
т.е. у людей на странице должны появлятся только свои сообщения и сообщения их друзей.

подскажите, пожалуйста, как на таблицы правильно поставить индексы и сделать правильный запрос с сортировкой?

Код:
CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL auto_increment,
  `user_id` int(11) NOT NULL default '0',
  `date` datetime NOT NULL default '0000-00-00 00:00:00',
........
  UNIQUE KEY `id` (`id`),
  KEY `uiddy` (`user_id`),
  KEY `useridid` (`user_id`,`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;

CREATE TABLE IF NOT EXISTS `friends` (
  `uid` int(11) NOT NULL,
  `friend_id` int(11) NOT NULL,
  UNIQUE KEY `uid` (`uid`,`friend_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

такой запрос просто летает:
Код:
SELECT * FROM friends f
LEFT JOIN posts p ON f.friend_id=p.user_id
WHERE f.uid=1 LIMIT 0,10;
запрос выполняется за 0,0005 сек.

Код:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra
1 	SIMPLE 	f 	ref 	uid 	uid 	4 	const 	127 	Using index
1 	SIMPLE 	p 	ref 	uiddy,useridid 	uiddy 	4 	master.f.friend_id 	205

Но, если добавить сортировку (надо, чтобы последние сообщения были самыми первыми):
Код:
SELECT * FROM friends f
LEFT JOIN posts p ON f.friend_id=p.user_id
WHERE f.uid=1 ORDER BY p.id DESC LIMIT 0,10;
то происходит ужас, запрос выполняется очень много минут...

Код:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra
1 	SIMPLE 	f 	ref 	uid 	uid 	4 	const 	127 	Using index; Using temporary; Using filesort
1 	SIMPLE 	p 	ref 	uiddy,useridid 	uiddy 	4 	master.f.following 	205
Подскажите, как это можно сделать с сортировкой? Понятно что происходит фул-скан, но как этого избежать?
Спасибо
 

Вурдалак

Продвинутый новичок
Можно разбить на 2 простых. Запрос друзей и выборка постов. На posts индекс (user_id, id).
 

Grapefruit Lips

Новичок
Но тогда появляется Using filesort, всё тормозит:
Код:
SELECT user_id, ........ FROM posts
LEFT JOIN users ON posts.user_id=users.id  
WHERE user_id IN(2,3,4,7,8,11,12,13,15,16,17,21,25,26,28,31,32,34,...много ай-ди друзей)   
ORDER BY posts.id DESC LIMIT 0, 10
ай-ди друзей мы взяли запросом ранее.
Если в этом же запросе намеренно указать индекс: FORCE INDEX(id), то тогда Using where по индексу, но время уже 1-2-3 секунды.

Неужели нет простого решения, чтобы запрос выполнялся быстро?
Постов 5,000,000

Вроде тот первый быстрый запрос то, что надо, но вопрос в том, как это отстортировать?
 

prolis

Новичок
select * from friends f, post p,
(select p.id, p.user_id from post p ORDER BY posts.id DESC LIMIT 0, 10) t
where f.friend_id=t.user_id
and p.id=t.id
order by p.id desc
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
неужели никто не хочет сделать за лентяя его работу? :)
 

weregod

unserializer
Grapefruit Lips, чтобы не считали лентяем, потрудитесь объяснить, что написал prolis
 
Сверху