SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 04.09.2008 16:52:49

Proger
Активист
Откуда: Санкт-Петербург
Зарегистрирован: 04.09.2008
Сообщений: 172

Оптимизировать несколько запросов

Здраствуйте.
Вопрос в том как "это" соединить или сократить, а то получается 1 + колво форумов * 2 запросов только для одного вывода главной страницы. Время обработки небольшое довольно таки, но и нагрузка на сервер пока просто не велика.

Есть запрос:

Код:

SELECT cat.cid, cat.name as cname, forum.fid, forum.name, forum.desc, forum.c, COUNT( DISTINCT topic.id ) AS topics, COUNT( DISTINCT post.pid ) AS posts
FROM cat
LEFT JOIN forum ON cat.cid = forum.c AND cat.gid = forum.gid
AND cat.gid = forum.gid
LEFT JOIN post ON post.fid = forum.fid AND cat.gid = post.gid
AND cat.gid = forum.gid
LEFT JOIN topic ON post.fid = topic.fid AND cat.gid = topic.gid
AND topic.gid = forum.gid
WHERE forum.gid = 1 (например)
GROUP BY forum.name
ORDER BY forum.c, forum.fid ASC
LIMIT 0, 100

он выбирает список форумов, категорий и количество тем и сообщений в них для скрипта форума. С него я делаю главную страницу форума, но потом пришла мысль добавить например "последнее сообщение в форуме", то есть название темы, и ссылка на неё с временм последнего сообщения в ней.

и идет цикл с разбором первого запроса и в нём подзапросы пришлось сделать

Код:

$query = "SELECT aid,pid,time,tid FROM `forum`.`post` WHERE gid=".$gid." AND fid=".$id." ORDER BY `time` DESC LIMIT 0,1";
$res = mysql_query($query);
$res = mysql_fetch_assoc($res);

$q = "SELECT name FROM `forum`.`topic` WHERE id=".$res['tid'];
$r = mysql_query($q);
$r = mysql_fetch_assoc($r);

$id = ид форума который сейчас выводиться.

Структура таблиц:

Код:

--
-- Структура таблицы `cat`
--

CREATE TABLE `cat` (
  `gid` tinyint(4) NOT NULL COMMENT 'Номер группы где категория',
  `cid` tinyint(3) NOT NULL COMMENT 'Ид категории в форуме группе',
  `name` varchar(50) NOT NULL COMMENT 'Имя категории',
  `st` varchar(4) NOT NULL default 'OPEN' COMMENT 'Приватность',
  KEY `id` (`cid`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

--
-- Структура таблицы `forum`
--

CREATE TABLE `forum` (
  `gid` int(5) NOT NULL COMMENT 'Номер группы гдбе форум',
  `c` tinyint(2) NOT NULL COMMENT 'Категория где этот форум',
  `fid` tinyint(2) NOT NULL COMMENT 'Ид форума в группе (не зависит от категории и считается (все форумы+1))',
  `name` varchar(50) NOT NULL COMMENT 'Название форума',
  `desc` varchar(250) NOT NULL COMMENT 'Описание форума',
  `st` enum('OPEN','CLOSED') default 'OPEN' COMMENT 'Статус/приватность форума'
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

--
-- Структура таблицы `post`
--

CREATE TABLE `post` (
  `gid` int(4) NOT NULL COMMENT 'Номер группы где пост',
  `fid` tinyint(4) NOT NULL COMMENT 'Номер форума где пост',
  `tid` int(4) NOT NULL COMMENT 'Номер топика, где пост',
  `pid` int(4) NOT NULL auto_increment COMMENT 'УНИКАЛЬНЫЙ для всего сайта ид поста',
  `aid` int(4) default NULL COMMENT 'Ид автора поста',
  `text` text NOT NULL COMMENT 'Текст сообщения',
  `time` datetime NOT NULL COMMENT 'Дата/время добавления сообщения в форум',
  PRIMARY KEY  (`pid`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=120 ;

--
-- Структура таблицы `topic`
--

CREATE TABLE `topic` (
  `gid` tinyint(4) NOT NULL COMMENT 'Номер группы, где топик',
  `id` tinyint(4) NOT NULL auto_increment COMMENT 'Уникальный для всего сайта ид топика',
  `fid` tinyint(4) NOT NULL COMMENT 'Ид форума, где топик',
  `aid` tinyint(4) NOT NULL COMMENT 'Ид автора топика',
  `name` varchar(100) NOT NULL COMMENT 'Название темы',
  `date` datetime NOT NULL COMMENT 'Дата создания темы',
  `lasttime` datetime NOT NULL,
  `st` enum('OPEN','CLOSE','PRIVATE','TRASH') default NULL COMMENT 'Приватность/статус темы',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=22 ;

Может надо UNION? Но я не умею его использовать.

Неактивен

 

#2 05.09.2008 11:03:06

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3878

Re: Оптимизировать несколько запросов

Для того, чтобы показывать последнее сообщение на форуме имеет смысл денормализовать таблицы. То есть добавить lastlostid в таблицу forum и следить за его обновлением.

Можно использовать тот факт, что более новые сообщения имеют и больший номер
SELECT fid, MAX(tid) FROM `forum`.`post` WHERE gid=".$gid. "GROUP BY fid";
Но в этом случае для определения времени последнего сообщения придется использовать подзапрос.

Неактивен

 

#3 06.09.2008 02:47:18

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 845

Re: Оптимизировать несколько запросов

С другой стороны, подзапрос по ключу должен выполняться достаточно быстро..

Неактивен

 

#4 06.09.2008 23:03:41

Proger
Активист
Откуда: Санкт-Петербург
Зарегистрирован: 04.09.2008
Сообщений: 172

Re: Оптимизировать несколько запросов

Хм... интерестно. На другом форуме мне тоже посоветовали хранить просто как можно больше "готовых" данных, чтобы увеличить производитльность. В частности мои COUNT'ы заменить на число которое, при создании темы/сообщения + 1 и в админке если что сделать уже пересчет.
Спасибо за ответы, буду думать.

Неактивен

 

#5 07.09.2008 02:12:18

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 845

Re: Оптимизировать несколько запросов

А всегда ищется баланс между хранением избыточных данных и скоростью выполнения запроса.
Иногда бывает выгоднее пожертвовать небольшим количеством места под избыточную колонку.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson