我正在使用大量数据构建SQL查询,但查询速度太慢
我有3张桌子; movies
,movie_categories
,skipped_movies
movies
表已标准化,我正在尝试根据类别查询电影,同时从skipped_movies
表中排除ID。
但是我在我的查询中尝试使用WHERE IN和WHERE NOT IN。
movies
表约有。 200万行(id,name,score)
movie_categories
约。 500万(id,movie_id,category_id)
skipped_movies
约有。 1k行(id,movie_id,user_id)
当skipped_movies
表非常小10到20行时,查询速度非常快。 (大约40 - 50毫秒)但是当表格大约有1k的数据时,我在查询上大约需要7到8秒。
这是我正在使用的查询。
SELECT SQL_NO_CACHE * FROM`movies` WHERE`id`IN(SELECT`movors_id` FROM`movie_categories` WHERE`category_id` = 1)AND`id` NOT IN(SELECT`movie_id` FROM`lepeped_movies` WHERE`user_id` = 1)AND`得分'< = 9 ORDER BY`得分`DESC LIMIT 1;
我已经尝试了许多想到的方法,但这是最快的方法。我甚至尝试了EXISTS
方法。
我正在使用SQL_NO_CACHE进行测试。
我猜ORDER BY语句运行速度非常慢。
答案 0 :(得分:1)
假设(movie_id,category_id)在movies_categories表中是唯一的,我将使用连接操作而不是子查询来获取指定的结果。
要排除“跳过”电影,反连接模式就足够了......这是一个左外连接,用于在skipped_movies中查找匹配的行,然后在WHERE子句中使用谓词排除找到的任何匹配,只留下行没有比赛。
SELECT SQL_NO_CACHE m.*
FROM movies m
JOIN movie_categories c
ON c.movie_id = m.id
AND c.category_id = 1
LEFT
JOIN skipped_movies s
ON s.movie_id = m.id
AND s.user_id = 1
WHERE s.movie_id IS NULL
AND m.score <= 9
ORDER
BY m.score DESC
LIMIT 1
适当的指数可能会提高绩效......
... ON movie_categories (category_id, movie_id)
... ON skipped_movies (user_id, movie_id)
答案 1 :(得分:1)
大多数IN / NOT IN查询可以使用JOIN / LEFT JOIN表示,这通常可以提供最佳性能。
将您的查询转换为使用联接:
SELECT m.*
FROM movies m
JOIN movie_categories mc ON m.id = mc.movie_id AND mc.category_id = 1
LEFT JOIN skipped_movies sm ON m.id = sm.movie_id AND sm.user_id = 1
WHERE sm.movie_id IS NULL
AND score <= 9
ORDER BY score DESC
LIMIT 1
答案 2 :(得分:0)
您的查询似乎没问题。只是一个小小的调整需要。您可以将* with替换为表中的列/属性名称。它将使这个查询比以往任何时候都更快。由于*操作非常慢