2010-10-04 1 views
2

2 таблицы по-прежнему очень малы по сравнению с тем, как они будут в будущем. Уже при проведении тестов по некоторым регулярным запросам возникают проблемы с производительностью.(MySQL) Наибольшее количество По группам Внутреннее соединение, проблемы с производительностью

Может ли кто-нибудь просветить меня по лучшей структуре таблицы или запросу?

====

Таблица 1: tv_show (в настоящее время 117 строк)

Таблица 2: tv_episodes (в настоящее время 43000 строк).

tv_show содержит идентификатор, который мы называем t_id на tv_episodes.

tv_episodes содержит этот t_id и поле называется episodes_num.

каждый эпизод имеет эпизод номер и сезона номер, episodes_num является общее количество эпизодов, независимо от сезона.

, например: все сезоны 10 эпизодов: Сезон 2 эпизод 1 = episodes_num:

Теперь для запроса: Я хочу, чтобы для каждых ТВ показывают последние episodes_num.

SELECT tv.*,ep.* FROM tv_show tv 
INNER JOIN tv_episodes ep ON (tv.id = ep.t_id) 
LEFT OUTER JOIN tv_episodes ep2 
ON (tv.id = ep2.t_id AND ep.episode_num < ep2.episode_num) 
WHERE ep2.t_id is NULL 

Это работает, но дает серверу очень трудно (запрос выше 10 секунд!)

Пожалуйста, помогите.

Edit: MySQL версии: * 5.1.47

Update: Спасибо за др решений, это тот, который является самым быстрым.

SELECT tv_episodes.* ,tv_show.* 

    FROM tv_episodes 
    INNER JOIN 
    (
     SELECT t_id, MAX(episode_num) AS episode_num 

     FROM tv_episodes 
     GROUP BY t_id 
    ) max_eps 
    ON tv_episodes.t_id = max_eps.t_id AND tv_episodes.episode_num = max_eps.episode_num 
    INNER JOIN 
tv_show ON tv_show.id=tv_episodes.t_id 



CREATE TABLE `tv_show` (
`id` int(255) NOT NULL AUTO_INCREMENT, 
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
`specification` varchar(50) NOT NULL, 
`year` int(4) NOT NULL, 
`status` varchar(100) NOT NULL, 
PRIMARY KEY (`id`), 
KEY `name` (`name`), 
KEY `specification` (`specification`), 
KEY `year` (`year`), 
KEY `status` (`status`) 
) ENGINE=MyISAM AUTO_INCREMENT=118 DEFAULT CHARSET=latin1 





CREATE TABLE `tv_episodes` (
`id` int(255) NOT NULL AUTO_INCREMENT COMMENT 'e_id', 
`t_id` int(200) NOT NULL, 
`season` int(2) NOT NULL, 
`episode` int(4) NOT NULL, 
`episode_num` int(10) NOT NULL, 
`airing` date NOT NULL, 
`online` enum('1','2') NOT NULL COMMENT '1=yes 2=no', 
`added` int(15) NOT NULL, 
`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
PRIMARY KEY (`id`), 
KEY `t_id` (`t_id`), 
KEY `season` (`season`), 
KEY `episode` (`episode`), 
KEY `season_num` (`episode_num`), 
KEY `airing` (`airing`), 
KEY `added` (`added`) 
) ENGINE=MyISAM AUTO_INCREMENT=43420 DEFAULT CHARSET=latin1 

ответ

1

Обновление: Основываясь на ваших последних комментариях и моей собственной настройке, я отредактировал свой ответ.

Это должно вернуть tv_episode записи для каждого tv_id имеющих максимальной episodes_num

SELECT tv_episodes.* 
FROM tv_episodes 
INNER JOIN 
(
    SELECT t_id, MAX(episodes_num) AS episodes_num 
    FROM tv_episodes 
    GROUP BY t_id 
) max_eps 
ON tv_episodes.t_id = max_eps.t_id AND tv_episodes.episodes_num = max_eps.episodes_num; 
+0

Это только начало: сделать его более понятным. В объединениях будет добавлено больше таблиц, называемых tv_show_info, tv_plots, tv_genres. Мне нужен список последних телевизионных эпизодов с ТВ-шоу name + info. это цель. Ваш последний запрос дал почти такое же время выполнения, как и мое .. спасибо за все ваши данные! –

+0

Большое спасибо! это последний запрос, который я искал ... Время запроса - это хорошо, и он получает результаты. –

0

Если вы используете MSSQL 2005 из выше (вы не указали систему базы данных и версии), вы можете использовать "ПРИМЕНИТЬ" clausule:

SELECT 
    tv.*,ep.* 
FROM tv_show tv 
CROSS APPLY (
    SELECT TOP 1 * FROM tv_episodes 
     WHERE t_id = tv.id 
     ORDER BY episode_num DESC 
) ep 
+0

спасибо за ваш ответ, но это не будет работать с моей версией. –

0

UPDATE: Попробуйте это -

Select tv.name as Tv_Show_Name,Max(episode_num) as Latest_Episode_Number from tv_show tv inner join tv_episode te 
on tv.id=te.t_id 
group by te.t_id,tv.name,episode_num 
+0

Благодарим вас за ответ. , но я хочу, чтобы последний эпизод из каждого телевизионного шоу «сгруппирован по» телешоу. –

+0

Благодарим вас за ввод, но он не дает уникальных телевизионных шоу –

+0

hmm..sorry У меня нет mysql на моем компьютере, чтобы проверить ... я немного изменил свой запрос ... если он работает ... но он должен быть простым ... и не присоединяться дважды, как вы делаете. – Vishal

0

Попробуйте это:

SELECT tv.*,ep.* FROM tv_show tv 
INNER JOIN episodes ep ON (tv.id = ep.t_id) 
WHERE ep.episode_num > ALL(SELECT x.episode_num FROM tv_episodes x WHERE x.episode_num != ep.episode_num) 
1

Производительность запроса - это не просто функция структурирования запроса, но и то, какие индексы были определены в базовых таблицах.

+0

вы можете увидеть индексы, могут ли быть какие-либо улучшения? –

 Смежные вопросы

  • Нет связанных вопросов^_^