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

Таблицы
видео: id
рейтинги: id, video_id, user_id, рейтинг

У одного видео может быть несколько оценок. Таблица видео содержит более 10 000 строк. Для некоторых видео может еще не быть связанных с ними рейтинговых данных.

Я хочу выбрать все видео, где определенный пользователь (в данном случае user_id 1) еще не оценил.

Запрос:

SELECT 
    videos.id, 
    (SELECT count(id) FROM ratings WHERE user_id = 1 AND ratings.video_id = videos.id) 
    AS rating_count    
FROM videos   
LEFT JOIN ratings ON ratings.video_id = videos.id  
GROUP BY videos.id  
HAVING rating_count = 0  
ORDER BY ratings.rating DESC   
LIMIT 20

Запрос занимает не менее 4 секунд каждый раз. Возможно, я не должен использовать здесь левое соединение?


person Tony Paternite    schedule 26.03.2014    source источник


Ответы (1)


Вы можете удалить свой подзапрос и переписать свой запрос, как показано ниже, также вы можете использовать условие идентификатора пользователя AND ratings.user_id = 1 в своем предложении on присоединения, поэтому все видео будут возвращены, даже если они не связаны с этим пользователем.

SELECT 
    videos.id, 
    count(ratings.id)  AS rating_count    
FROM videos   
LEFT JOIN ratings 
ON (ratings.video_id = videos.id   AND ratings.user_id = 1)
GROUP BY videos.id  
HAVING rating_count = 0  
ORDER BY ratings.rating DESC   
LIMIT 20
person M Khalid Junaid    schedule 26.03.2014
comment
Спасибо. Это немного помогает. Тем не менее, он по-прежнему работает примерно 2,5 секунды каждый раз. - person Tony Paternite; 26.03.2014
comment
@TonyPaternite, используя приведенный выше запрос, вам нужен составной индекс для create index my_idx on ratings (video_id, user_id); - person M Khalid Junaid; 26.03.2014
comment
Вау! Это потрясающе! Огромное спасибо!! - person Tony Paternite; 26.03.2014