Reputation: 303
I use the following query to get years
and the number of movies released in that year
which(referring to a movie) has a female actor.
It executes successfully, but it is taking 4 minutes to execute.
How do I get results in less time?
Also, my disk use goes to more than 70% during this execution.
SELECT m.year, COUNT(m.id)
FROM movies m
JOIN roles r ON m.id=r.movie_id
JOIN actors a ON r.actor_id=a.id
WHERE a.gender='F'
GROUP BY m.year;
Upvotes: 0
Views: 170
Reputation: 31832
Your query is perfectly fine, if it returns the desired result. I've imported the imdb.sql
and your query executes in 17 seconds on my PC. The EXISTS solution from the other answer needs 48 seconds and returns a different result.
The original tabes are using the MyISAM engine and are quite poorly indexed. After converting the three tables to InnoDB, your query executes in 2.3 seconds. InnoDB takes about twice as much space - But I think it's worth the performance boost.
Then the following changes
ALTER TABLE `actors` ADD INDEX `gender` (`gender`);
ALTER TABLE `roles`
DROP INDEX `idx_actor_id`,
ADD INDEX `idx_actor_movie` (`actor_id`, `movie_id`);
decreased the execution time to 1.7 seconds. That is 10 times faster than with the original schema.
Upvotes: 1
Reputation: 2006
I think you can use
EXISTS
instead of JOIN.
SELECT m.year, COUNT(m.id) FROM movies m
where
exists (select * from roles r where r.movie_id=m.id and
exists(select * from actors a where a.id=r.actor_id and a.gender='F'))
group by m.year;
To display Total Movies Per Year along with above output.
select t1.year,t1.count,t2.total from
(
SELECT m.year as year, COUNT(m.id) as count FROM movies m
where exists (select * from roles r where r.movie_id=m.id and exists(select * from actors a where a.id=r.actor_id and a.gender='F'))
group by m.year
)t1
join
(select year,count(m.id) as total from movies m group by m.year) t2
on t1.year=t2.year;
Upvotes: 3