У меня есть веб-страница, где пользователи загружают и смотрят видео. На прошлой неделе я спросил , как лучше всего отслеживать просмотры видео, чтобы я мог отображать самые просматриваемые видео на этой неделе (видео со всех дат).
Теперь мне нужна помощь в оптимизации запроса, с помощью которого я получаю видео из базы данных. Соответствующие таблицы таковы:
video (~239371 rows)
VID(int), UID(int), title(varchar), status(enum), type(varchar), is_duplicate(enum), is_adult(enum), channel_id(tinyint)
signup (~115440 rows)
UID(int), username(varchar)
videos_views (~359202 rows after 6 days of collecting data, so this table will grow rapidly)
videos_id(int), views_date(date), num_of_views(int)
Таблица video
содержит видео, signup
содержит пользователей и videos_views
содержит данные о просмотрах видео (каждое видео может иметь одну строку в день в этой таблице).
У меня есть этот запрос, который справляется с задачей, но для его выполнения требуется ~ 10 секунд, и я думаю, что со временем он будет только ухудшаться по мере увеличения таблицы videos_views
.
SELECT
v.VID,
v.title,
v.vkey,
v.duration,
v.addtime,
v.UID,
v.viewnumber,
v.com_num,
v.rate,
v.THB,
s.username,
SUM(vvt.num_of_views) AS tmp_num
FROM
video v
LEFT JOIN videos_views vvt ON v.VID = vvt.videos_id
LEFT JOIN signup s on v.UID = s.UID
WHERE
v.status = 'Converted'
AND v.type = 'public'
AND v.is_duplicate = '0'
AND v.is_adult = '0'
AND v.channel_id <> 10
AND vvt.views_date >= '2001-05-11'
GROUP BY
vvt.videos_id
ORDER BY
tmp_num DESC
LIMIT
8
Все соответствующие поля проиндексированы.
И вот скриншот результата EXPLAIN:
альтернативный текст http://img685.imageshack.us/img685/9440/explain.png
Итак, как я могу оптимизировать это?
UPDATE
Это мой запрос, основанный на ответе Quassnoi. Он возвращает правильные видео, но он портит JOIN в таблице регистрации. Для некоторых записей поле username
имеет значение NULL, для других оно содержит неправильное имя пользователя.
SELECT
v.VID,
v.title,
v.vkey,
v.duration,
v.addtime,
v.UID,
v.viewnumber,
v.com_num,
v.rate,
v.THB,
s.username
FROM
(SELECT
videos_id,
SUM(num_of_views) AS tmp_num
FROM
videos_views
WHERE
views_date >= '2010-05-13'
GROUP BY
videos_id
) q
JOIN video v ON v.VID = q.videos_id
LEFT JOIN signup s ON s.UID = v.VID
WHERE
v.type = 'public'
AND v.channel_id <> 10
AND v.is_adult = '0'
AND is_duplicate = '0'
ORDER BY
tmp_num DESC
LIMIT
8
Вот результат:
альтернативный текст http://img714.imageshack.us/img714/2954/resultu.png