2011-12-22 59 views
0

我已相對於閱讀速度問題通過MySQL和PHP得到一個隨機行,不知道怎麼我的代碼可能速度得到改善。我的優化排隨機取

我在一個名爲「旗幟」表數據庫歡迎信息,我想顯示相對於頁面上的位置隨機的橫幅,並添加+1到VIEW_COUNT爲這面旗幟。我的方法可行,但對於每次頁面加載都會發生這種情況的繁忙網站,這可以提高速度嗎?由於

/* Get banners for position 1 then choose a random one to display */ 
$banners = mysql_query("SELECT id,title,banner_url,destination FROM ".TBL_BANNERS." WHERE position = '1' AND status = '1'"); 
$banner_count = mysql_num_rows($banners) - 1; 
$rand_offset = mt_rand(0,$banner_count); 
$result = mysql_query("SELECT id,title,banner_url,destination FROM ".TBL_BANNERS." LIMIT $rand_offset, 1 "); 

$banner_id = mysql_result($result,0,"id"); 
$banner_title = mysql_result($result,0,"title"); 
$banner_url = mysql_result($result,0,"banner_url"); 
$banner_dest = mysql_result($result,0,"destination"); 

/* Add view to this banner */ 
$database->addViewToBanner($banner_id); 

最後一個函數使用查詢:

"UPDATE banners SET view_count = view_count+1 WHERE id = '$banner_id'" 

我還需要多說,有可能不會成爲任何超過100條記錄中的「橫幅」表在任何一個時間,但有會在ID中漏洞。這些ID可能會上升到200,但只有一半仍然存在。

+2

對不起,有什麼不對勁的錯'ORDER BY RAND()LIMIT 1'(實際上可能什麼不對的地方,我不是sarky,實際上,我問)? – DaveRandom 2011-12-22 16:57:44

+0

我讀過,當你在桌子上有洞的時候,這種方式並不是隨機的。比如我現在的ID返回了原來的查詢是9,15和16 – user29660 2011-12-22 17:06:46

+0

@DaveRandom是 - 做一個ORDER BY RAND()是資源密集型的,您注意到了很多更與數千個/百萬行的表。國際海事組織(IMO)在只有相對較少的行的表上使用它仍然很好。見http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/一個不錯的解釋。 – Nick 2011-12-22 17:09:02

回答

1

生成PHP中的隨機數和鑽這種方式進入PK

的SQL將

SELECT id,title,banner_url,destination 
FROM TBL_BANNERS 
WHERE id = $rand_offset 

如果你錯過了,再次運行。這給出了一個非常有效的尋求一個行,這將是比使用極限更好/偏移處理

+0

好的小費。我使用mysql_result從隨機行中獲取ID,並在第二個查詢中使用該ID。謝謝 – user29660 2011-12-22 17:12:19

+0

如果你已經有了一個隨機的行(爲了得到ID),那麼你不需要第二個'SELECT'來獲取其餘的數據 - 當你獲取ID時你可能會得到這些數據。問題在於如何首先獲得隨機行。 – Amadan 2011-12-22 17:26:53

+0

但原始查詢用於確保我抓取正確的記錄,而不是表中的每個記錄(WHERE position ='1'AND status ='1')。還有一些記錄被刪除,所以我不能隨便選擇一行。 – user29660 2011-12-22 17:36:31

0

代替第一SELECT的,使用此:

$banners_count_result = mysql_query("SELECT COUNT(*) AS num_banners FROM ".TBL_BANNERS." WHERE position = '1' AND status = '1'"); 
$banner_count = mysql_result($banners_count_result, 0, "num_banners"); 

除非你添加和刪除新的橫幅每隔幾秒鐘,考慮某處緩存這個結果。

+0

這肯定會使效率降低,因爲該查詢只會返回1條信息(行數)?如果我使用這個,我不會有一個隨機ID使用,所以它會使第二個查詢更復雜。 – user29660 2011-12-22 17:18:53

+0

該查詢爲您提供總行數。然後在PHP中生成一個1到現在的行數的隨機數,在第二個查詢中,像前面那樣使用LIMIT構造拉整行。無論如何你都在做兩個查詢,但你的第一個(選擇所有行,請求計數)的效率非常低。這個人做同樣的事情,但以一種非常有效的方式(選擇行數,得到單個結果行)。 – Amadan 2011-12-22 17:25:46

+0

我會想用PHP來計算行數比使用MYSQL方法更快,但我可能是錯的。即使即時通訊錯誤,它仍然會使第二個查詢效率降低,因爲我必須使用偏移LIMIT而不是僅僅是「WHERE ID =」子句。 – user29660 2011-12-22 17:47:51

1

做到這一點,最理想的方式,你可以在很多地方在互聯網,例如閱讀Anton Titov's blog是做2個查詢:

SELECT COUNT(*) AS banners FROM quotes 

然後生成您的編程語言中的隨機數(即PHP使用mt_rand)。並將其輸入到此查詢中:

SELECT * FROM banners LIMIT $generated_number, 1 

注意:如果您的表只有少量的行,則不適用。一般來說,我仍然使用ORDER BY RAND(),直到我知道表中會有超過100行。

+0

所以多個查詢不總是一件壞事?那麼完整的橫幅表在任何時候都不會有超過50條記錄,所以也許我更有效地使用ORDER BY RAND解決方案。 – user29660 2011-12-22 17:25:29

+0

並非總是如此。通常在處理IN(),NOT IN()或RAND()時,最好做第二個查詢。 – Nick 2011-12-22 17:32:18