(MySQL) Величайшее число По группам Внутреннее объединение, проблемы с производительностью - PullRequest
2 голосов
/ 04 октября 2010

2 таблицы все еще очень малы по сравнению с тем, как они будут в будущем. Уже при тестировании некоторых обычных запросов возникают проблемы с производительностью.

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

====

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

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

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

tv_episodes содержит этот t_id и поле с именем episodes_num .

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

например: во всех сезонах 10 эпизодов: 2 сезон 1 эпизод = число эпизодов: 11

Теперь по запросу: Я хочу, чтобы на каждом телешоу были самые последние эпизоды_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 секунд!)

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

Редактировать: версия MySQL: * 5.1.47

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

    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

Ответы [ 5 ]

1 голос
/ 04 октября 2010

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

При этом должны возвращаться записи tv_episode для каждого tv_id, имеющего максимальное число эпизодов

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;
1 голос
/ 04 октября 2010

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

0 голосов
/ 04 октября 2010

ОБНОВЛЕНИЕ : попробуйте -

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 голосов
/ 04 октября 2010

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

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)
0 голосов
/ 04 октября 2010

Если вы используете MSSQL 2005 и выше (вы не указали систему и версию базы данных), вы можете использовать условие «APPLY»:

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
...