2014-11-05 91 views
-1

此查詢在某些where子句之後從500k記錄的表中提取隨機Movie。該查詢的速度範圍從0.016s到0.450s。任何人都可以看到一種改進方法,使其大約比0.450大0.016?如何提高此查詢獲取隨機行的速度

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

@MarcB它不是一個笨蛋。我試圖改進一個類似於該問題頂部答案的查詢,但它不同於此答案,因爲該答案在沒有任何地方條件的情況下獲取了隨機行。另外我不想獲得10行,只有一個 – code511788465541441 2014-11-05 21:56:07

+0

並不重要,如果它不是你的確切查詢。這是答案中的重要概念。 – 2014-11-05 21:58:50

回答

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最高的行),但實際上它可能工作得很好。

+0

謝謝你的回答。刪除orderby似乎做了一個非常小的改進。但我不確定這樣做是否明智,是不是會影響結果的隨機性? – code511788465541441 2014-11-05 22:18:33

+0

@ code578841441。 。 。問題在於,時間上的差距是由於'order by'(隨機ID很小時)還是由於搜索匹配記錄造成的。 – 2014-11-05 22:40:41

0

一種簡單的技術是在該行中使用散列函數上的某些數據具有變化salt

select blah, blah, blah 
... 
order by password(concat(id, unix_timestamp())) 
limit 1 

的不同鹽確保每個執行產生不同隨機行。您仍需要添加行中的一些數據,以確保每行的排列順序與其他行不同。

+0

這很慢。始終在0.250左右 – code511788465541441 2014-11-05 22:19:04