此查询从somek子句后的500k记录表中获取随机Movie。此查询的速度范围为0.016秒到0.450秒。任何人都可以看到一种方法将它提高到0.016以上,大约是0.450大关吗?
SELECT movie.ID, imdbID, Title, Y
ear, Rating, Runtime, Genre, Metacritic,
imdbRating, imdbVotes, Poster, FullPlot,
Language,trailerUrl, type
from moviedb.movie
INNER JOIN (
SELECT RAND()*(
SELECT MAX(ID)
FROM movie
) AS ID) AS t
ON movie.ID >= t.ID
WHERE year > 2004
AND year < 2015
AND imdbRating > 6.9
AND imdbvotes > 9999.9
ORDER BY movie.id LIMIT 1
答案 0 :(得分:1)
您的查询基本上是这样的:
SELECT m.*
from moviedb.movie m JOIN
(SELECT RAND()*MAX(ID) as maxid
FROM movie
) mm
ON m.ID >= mm.max
WHERE m.year > 2004 AND m.year < 2015 AND m.imdbRating > 6.9 AND m.imdbvotes > 9999.9
ORDER BY m.id
LIMIT 1;
我怀疑性能变化是由order by
引起的。除非你可以说服MySQL使用order by
的索引,否则你可能无法解决这个问题。这样的索引是id, year, imdbrating, imdbvotes
。这是where
和order by
子句的覆盖索引,MySQL可能会使用它来避免文件排序。
另一种方法是为评级和投票计数引入标志。然后你可以将查询短语为:
where m.year > 2004 and m.year < 2015 and RatingGreatFlag = 1 and LotsaVotesFlag = 1
然后RatingGreatFlag, LotsVotesFlag, id, year
上的索引可能会有很大的帮助。但是,维护这些标志可能需要使用触发器。
编辑:
当我考虑这个问题时,我想知道删除order by
是否仍会产生你想要的东西。这会在随机id之后给出一个不确定的行。肯定有一些方法可以选择这样一个不好的行(例如id最高的行),但在实践中它可能会很好用。
答案 1 :(得分:0)
一种简单的技术是对行中的某些数据使用散列函数,其变化为salt:
select blah, blah, blah
...
order by password(concat(id, unix_timestamp()))
limit 1
变化的盐确保每次执行产生不同的随机行。您仍然需要从行中添加一些数据,以确保每行的排序与每个其他行的顺序不同。