Помогите оптимизировать запрос, пожалуйста

Фанат

oncle terrible
Команда форума
Помогите оптимизировать запрос, пожалуйста

Есть таблица
[sql]CREATE TABLE `Board` (
`id` int(10) unsigned NOT NULL auto_increment,
`date` datetime default NULL,
`title` varchar(64) default NULL,
`author` varchar(32) default NULL,
`body` text,
`root` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `date` (`date`),
KEY `root` (`root`)
)[/sql]
И такой вот запрос
[sql]explain SELECT max(b1.date), b2.id FROM Board b1 LEFT JOIN Board b2 on b2.id=b1.root GROUP BY b1.root[/sql]
Код:
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
| table | type   | possible_keys | key     | key_len | ref     | rows | Extra                           |
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
| b1    | ALL    | NULL          | NULL    |    NULL | NULL    | 4999 | Using temporary; Using filesort |
| b2    | eq_ref | PRIMARY       | PRIMARY |       4 | b1.root |    1 | Using index                     |
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
Объясните дураку, плиз
1. можно ли оптимизировать это?
2. может быть, выбирать надо вообще по-другому?

Это форум, на примитивной однотабличной основе.
в поле root пишется id первого сообщения.
Хочется построить форум одним запросом.
Запрос приведен упрощенный, но рабочий.
Я рассуждаю как? группируем таблицу по root и джойним на себя же по id=root чтобы выбрать заголовок и автора первого сообщения.
 

tony2001

TeaM PHPClub
может, лучше сделать "синтетическую" запись с нулевым или первым ID и считать её корнем?
в этом случае, можно будет избежать LEFT JOIN и использовать обычный джойн.
 

jer

...
мое мнение: особо нечего оптимизировать.
а что долго выполняется?

или ты чисто из спортивного интереса?
 

Фанат

oncle terrible
Команда форума
Ну, я бы не назвал этот интерес чисто спортивным.
И я не соглашусь с тем, что "Using temporary; Using filesort" - это означает, что оптимизировать нечего. Скорее, как раз наоборот.
Выполняется - тоже не скажу, чтобы было быстро: секунду.
С точки зрения юзера - незаметно. Но мне кажется, что это многовато.

-~{}~ 10.11.04 12:26:

tony2001
Если честно, не очень понял.
Но тупо заменил лефт джойн на обычный.
картина не изменилась.
Код:
explain SELECT max(b1.date), b2.id FROM Board b1, Board b2 WHERE b2.id=b1.root GROUP BY b1.root;
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
| table | type   | possible_keys | key     | key_len | ref     | rows | Extra                           |
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
| b1    | ALL    | root          | NULL    |    NULL | NULL    | 4999 | Using temporary; Using filesort |
| b2    | eq_ref | PRIMARY       | PRIMARY |       4 | b1.root |    1 | Using where; Using index        |
+-------+--------+---------------+---------+---------+---------+------+---------------------------------+
 

Screjet

Новичок
Нету конкретного условия "что выбираем" потому мускул и перелопачивает все.

Может есть смысл добавить
WHERE b1.root IS NOT NULL
?
 

Profic

just Profic (PHP5 BetaTeam)
Единственное, что приходит в голову, это сделать индекс
root_date (root, `date`) и изменить запрос на
[sql]SELECT b1.root, max( b1.date)
FROM Board b1 use index (root_date)
LEFT JOIN Board b2 ON b2.id = b1.root
GROUP BY b1.root[/sql]
Должно по идее (согласно http://dev.mysql.com/doc/mysql/en/GROUP_BY_optimization.html) даль некоторый прирост. Но что думает по этому поводу муська никому кроме нее самой не известно :)
 

chira

Новичок
если предполжить, что у начала ветки id = root ...
без связывания получается другой результат?
Код:
SELECT max( b1.date ) , b1.root
FROM Board b1
GROUP BY b1.root
-~{}~ 10.11.04 14:25:

в твоём селекте
SELECT max( b1.date ) , b2.id
FROM Board b1
LEFT JOIN Board b2 ON b2.id = b1.root
GROUP BY b1.root

b2.id значение будет не предсказуемо ... обычно возвращается первое которое найтся SQL сервером ...
 

.des.

Поставил пиво кому надо ;-)
Если хочется получить дату и ид сообщения, которому эта дата соответствует, то скорее всего это два запроса через временную таблицу.

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

Фанат

oncle terrible
Команда форума
Спасибо, я как раз хотел написать в ответ Тони, что если менять формат, то заводить отдельную таблицу с заголовками.
Это мне тоже представляется самым оптимальным решением.
Заодно можно получить и автора последнего сообщения, к примеру. Сейчас-то для этого надо либо еще один джойн, либо запрос.
 
Сверху