Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Оптимизация запроса (MySQL)


Страницы:   1 2 3

Piter ©   (2006-08-08 22:32:00) 

Очень интересно, почему такой запрос не нехилой машине выполняется порядка 40 секунд:

SELECT p.id, p.name, p.title, p.added_date, p.added_time,
ca.name AS category_name,
COUNT(f.publication_id) AS count
FROM cb_publications AS p
LEFT JOIN cb_categories AS ca
ON (p.category_id = ca.id)
LEFT JOIN cb_favorites AS f
ON (p.id = f.publication_id)
GROUP BY p.id
HAVING count > 0
ORDER BY count DESC
LIMIT 10;


Записей в cb_publications: 7644
Записей в cb_categories: 9
Записей в cb_favorites: 5257

База MySQL.

CREATE TABLE IF NOT EXISTS `cb_publications` (
 `id` int(10) unsigned NOT NULL auto_increment,
 `category_id` int(10) unsigned NOT NULL default '0',
 `rubric_id` int(10) unsigned NOT NULL default '0',
 `user_id` int(10) unsigned NOT NULL default '0',
 `name` varchar(255) NOT NULL default '',
 `unixtime` int(10) unsigned NOT NULL default '0',
 `added_date` date NOT NULL default '0000-00-00',
 `added_time` time NOT NULL default '00:00:00',
 `activated_unixtime` int(10) unsigned NOT NULL default '0',
 `is_active` tinyint(3) unsigned NOT NULL default '0',
 `is_moderated` tinyint(3) unsigned NOT NULL default '0',
 `front_page` tinyint(3) unsigned NOT NULL default '0',
 `title` varchar(100) NOT NULL default '',
 `content` text NOT NULL,
 `poll_question` varchar(255) NOT NULL default '',
 `source` varchar(255) NOT NULL default '',
 `source_url` varchar(255) NOT NULL default '',
 `views` int(10) unsigned NOT NULL default '0',
 `rating` float unsigned NOT NULL default '0',
 `rating_votes` int(10) unsigned NOT NULL default '0',
 `comments_count` int(10) unsigned NOT NULL default '0',
 `keywords` varchar(255) NOT NULL default '',
 `allow_comments` tinyint(3) unsigned NOT NULL default '1',
 PRIMARY KEY  (`id`),
 KEY `front_page` (`front_page`),
 KEY `is_active` (`is_active`),
 KEY `is_moderated` (`is_moderated`),
 KEY `category_id` (`category_id`),
 KEY `rubric_id` (`rubric_id`),
 KEY `user_id` (`user_id`),
 KEY `keywords` (`keywords`),
 KEY `name` (`name`,`added_date`)
) TYPE=MyISAM AUTO_INCREMENT=1226 ;


CREATE TABLE IF NOT EXISTS `cb_categories` (
 `id` int(10) unsigned NOT NULL auto_increment,
 `position` smallint(5) unsigned NOT NULL default '0',
 `name` varchar(255) NOT NULL default '',
 `title` varchar(100) NOT NULL default '',
 `description` text NOT NULL,
 `adv_title` varchar(100) NOT NULL default '',
 `adv_text` text NOT NULL,
 `adv_show` tinyint(3) unsigned NOT NULL default '0',
 PRIMARY KEY  (`id`),
 UNIQUE KEY `name` (`name`)
) TYPE=MyISAM AUTO_INCREMENT=16 ;


CREATE TABLE IF NOT EXISTS `cb_favorites` (
 `user_id` int(10) unsigned NOT NULL default '0',
 `publication_id` int(10) unsigned NOT NULL default '0',
 `unixtime` int(10) unsigned NOT NULL default '0',
 PRIMARY KEY  (`user_id`,`publication_id`)
) TYPE=MyISAM;


Slym   (2006-08-11 10:46:00) [1]

Piter ©   (10.08.06 13:35) [40]
"#1064 - You have an error in your SQL syntax

Я же заранее предупредил "Это псевдокод" и копипастом не сработает.
И привел принцип: выбираем сначала данные (подзапросом)
а уж к ним цепляем расшифровку жойним Титлы и Наймы


Sergey13   (2006-08-10 16:59:00) [2]

> [44] roottim ©   (10.08.06 16:46)

Таки наверное с 8i. У меня вроде тоже нет блокировки.


evvcom   (2006-08-10 16:57:00) [3]


> [43] Sergey13 ©   (10.08.06 16:32)
> Не по 7-ке же она написана.

Не, не по 7-ке. Я видел там упоминание 8-ки.

> [44] roottim ©   (10.08.06 16:46)

Вероятно, так и есть. Потому я и упомянул свою версию.


roottim   (2006-08-10 16:46:00) [4]

C Oracle 9-ки блокировка таблицы при отсутствии индекса по FK канула в лету


Sergey13   (2006-08-10 16:32:00) [5]

> [42] evvcom ©   (10.08.06 15:51)
> У меня 9.2.0.6, видимо Кайт описывал что-то более раннее.
Возможно. Хотя у меня 8.1.7. Не по 7-ке же она написана.


evvcom   (2006-08-10 15:51:00) [6]

> [41] Sergey13 ©   (10.08.06 14:36)

Да, вижу теперь у Кайта. Попробовал [25] еще раз, но уже с 'изменением' первичного ключа. Результат тот же. Все ок. У меня 9.2.0.6, видимо Кайт описывал что-то более раннее.


Sergey13   (2006-08-10 14:36:00) [7]

> [25] evvcom ©   (09.08.06 15:04)

Таки нашел я где видел сие утверждение. Вернее видел это и ранее, но нашел подтверждение. У Кайта в его "Оракл для профессионалов" в главе 7 "Индексы" есть подраздел "Индексы для внешних ключей".


Piter   (2006-08-10 13:35:00) [8]

попробовал:

SELECT p.id, p.name, p.title, p.added_date, p.added_time,
ca.name AS category_name, MostFavor.count as count
FROM
(SELECT TOP 10 cb_favorites.publication_id, count(cb_favorites.publication_id) as count
FROM (cb_favorites
GROUP BY cb_favorites.publication_id
ORDER BY count(cb_favorites.publication_id)) as MostFavor
INNER JOIN cb_publications AS p
ON (MostFavor. publication_id = p.id))
INNER JOIN cb_categories AS ca
ON (p.category_id = ca.id)
ORDER BY count(cb_favorites.publication_id) desc;


Результат:

"#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '10 cb_favorites . publication_id , count( cb_favorites . publication_id ) as cou' at line 1 "


Piter   (2006-08-10 13:25:00) [9]

Slym ©   (09.08.06 16:57) [34]
Мой вариант не пробывал?


не, не пробовал. Меня полностью устроило ускорение в 10 раз :)

Хотя если интересно - могу попробовать...


evvcom   (2006-08-09 17:11:00) [10]

> [37] ANB ©   (09.08.06 17:03)
> Для проверки возможности апдейта/удаления.

Конечно же. Удаления согласен полностью. Апдейта - только ключа по которому констрейнт, обычно это primary key. Неточно оформил свою мысль, т.к. удалением подобных записей мы тоже не занимаемся, а вводим дополнительное поле флага, дабы обезопасить себя от "нечаянных" действий пользователя.


ANB   (2006-08-09 17:03:00) [11]


> Ни на один FK у меня нет индексов, которые актуальны только
> (как я думал до сих пор) с каскадными констрейнтами, чего
> мы тоже не используем.

Неправильно думал. Для обычных констрейнтов они тоже используются. Для проверки возможности апдейта/удаления. Чтобы поругаться.


evvcom   (2006-08-09 17:01:00) [12]

> [33] Piter ©   (09.08.06 16:49)
> И зачем придумали внешние JOIN'ы если можно в 10 раз быстрее?

Действительно! Нафига зад... бог человеку придумал, ведь через горло гланды гораздо удобнее выдирать! :-)
Затем, что весь спектр задач не ограничивается только твоей задачей.


Sergey13   (2006-08-09 16:58:00) [13]

> [33] Piter ©   (09.08.06 16:49)

Джоины всякие нужны
Джойны всякие важны.

(с) Михалков или Маршак (почти)
8-)


Slym   (2006-08-09 16:57:00) [14]

Мой вариант не пробывал?


Piter   (2006-08-09 16:49:00) [15]

Sergey13, спасибо! Вместо 45 секунд запрос стал выполняться 1,5 секунды. Правда, при одинаковых Count чуть сортировка поменялась, да хрен с ней :)

И зачем придумали внешние JOIN'ы если можно в 10 раз быстрее?


evvcom   (2006-08-09 15:37:00) [16]

> [27] Piter ©   (09.08.06 15:15)

См. [31]. У меня Оракл.


Desdechado   (2006-08-09 15:32:00) [17]

Piter ©   (09.08.06 15:15) [27]
> а по-моему для FK индекс создается автоматически.
В IB - да, в Оракле - нет, в MySQL - не знаю.


Slym   (2006-08-09 15:30:00) [18]

ORDER BY count(cb_favorites.publication_id) desc
а строку ORDER BY count DESC; убрать


Slym   (2006-08-09 15:29:00) [19]

или
SELECT p.id, p.name, p.title, p.added_date, p.added_time,
ca.name AS category_name, MostFavor.count as count
FROM
(SELECT TOP 10 cb_favorites.publication_id, count(cb_favorites.publication_id) as count
FROM (cb_favorites
GROUP BY cb_favorites.publication_id
ORDER BY count(cb_favorites.publication_id)) as MostFavor
INNER JOIN cb_publications AS p
ON (MostFavor. publication_id = p.id))
INNER JOIN cb_categories AS ca
ON (p.category_id = ca.id)
ORDER BY count DESC;


Slym   (2006-08-09 15:20:00) [20]

Сначала подсчет потом красоты наводим
псевдокод не проверял:
SELECT p.id, p.name, p.title, p.added_date, p.added_time,
ca.name AS category_name, MostFavor.count as count
FROM
(SELECT cb_favorites.publication_id, count(cb_favorites.publication_id) as count
FROM (cb_favorites
GROUP BY cb_favorites.publication_id
ORDER BY count(cb_favorites.publication_id)
LIMIT 10) as MostFavor
INNER JOIN cb_publications AS p
ON (MostFavor. publication_id = p.id))
INNER JOIN cb_categories AS ca
ON (p.category_id = ca.id)
ORDER BY count DESC;


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо