如何提高此查询的速度以获取随机行

时间:2014-11-05 21:47:54

标签: mysql sql performance

此查询从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

2 个答案:

答案 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。这是whereorder 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

变化的盐确保每次执行产生不同的随机行。您仍然需要从行中添加一些数据,以确保每行的排序与每个其他行的顺序不同。