2009-11-05 151 views
1

我讀過,在大型數據庫上使用ORDER BY RAND()運行SQL查詢並不是一個好主意。隨機記錄Mysql PHP

因此,這是我在分解代碼時的一個鏡頭。代碼需要從數據庫中選擇10個隨機ID,然後再進行一次選擇以抓取隨機行。

$sql = "SELECT id FROM table WHERE image != '' 
     ORDER BY id DESC LIMIT 50;"; 

$result = mysql_query($sql); 


while($row = mysql_fetch_array($result)) 
{ 
    foreach($row as $key => $value) 
    { 
     $array[] = $value; 
    } 
} 
$rand_keys = array_rand($array, 10); 

foreach($rand_keys as $value) 
{ 

    $rand_arr[] = $array[$value]; 

} 
$rand_list = implode("," , $rand_arr); 

$sql = "SELECT image FROM table 
     WHERE image != '' 
     AND id IN ($rand_list)"; 
$result = mysql_query($sql); 

任何建議加快或簡化?

回答

2

四件事情:

  1. 你幹嗎打50 id■如果你只需要12? (你正在從最近的50個選擇12個ID - 這是有道理的,儘管在一般意義上這個詞不是特別隨意的 - 那是故意選擇你想要從中挑選行的子集?)。

  2. 你是否已經對SQL語句ORDER BY RAND()進行了概要分析,看看它是否對你來說很慢?你的數據集有多大?

  3. 在最後一個查詢中不需要WHERE image != '',因爲您已經選取了id s,其中image != ''

  4. 你爲什麼要做array_rand($array, 10) - 你說你想要12個值?

  5. 可以簡化挑選出隨機值是這樣的:

$rand_arr = array_rand(array_flip($array), 12);

+0

我真的會避免rand()作爲一般習慣。我已經看到了這個只有幾十萬行的MyISAM表。 – 2009-11-05 09:31:01

+0

來吧,現在多米尼克。 #3和#4是明顯的拼寫錯誤/被忽略的想法。我的錯。 #5非常有幫助。 #2在我心中。我在共享服務器上運行這段代碼,它使我的網站停下來(實際上與ORDER BY rand()效果相同)。這使我重新思考完全隨機的行,即。提供隨機圖像。 – rrrfusco 2009-11-17 01:21:10

0

我會用點1同意以上2 - 如果你能內進行的隨機數據的選擇您的應用程序與數據所在的同一級別相同,您需要編寫的程序才能完成同樣的任務。

0

有沒有特別好的方法來優雅地做到這一點。

但是你可以從很多方面入手。如果你的數據集大小合適(「rand()順序太大」,但不是太大),具有順序的id值,並且一般不會刪除太多,所以你總是可以這樣做:

SELECT MIN(id) as min, MAX(id) as max FROM table 

在「min」和「max」(含)之間生成N個隨機整數。我們把它稱爲50.如果你從不刪除表中的任何東西,N可能是12.如果你刪除,做一些餐巾算術,並找出一個好數字。你可能會偏高。

SELECT * FROM table WHERE id IN (<your set of integers>) AND image_id = '' LIMIT 12; 

檢查並確保你得到至少12條結果。如果沒有,基本上重複和結合。

對於大型集合,此方法應該比ORDER BY RAND()更好,尤其是如果您的ID序列不是非常稀疏。

+0

我喜歡這種方法,但它只適用於auto_increment單調的單主設置:auto_increment_increment,auto_increment_offset設置可以將這些id分散出去。 – 2009-11-05 09:28:56

+0

好點。這隻有在你開始處理多個主人時纔會起作用。 – timdev 2009-11-05 09:40:54

0

我會專注於Dominic的第5點,它是一種影響相當小的方式來隨機檢索數據。 你也可以sort()的ID列表(我相信MySQL檢測到這一點,並跳過爲你排序該列表。)

對於涉及物化視圖(實質上緩存表)的大數據集和高請求率還有其他技術。正試圖解決大型繁忙表格上的現有性能問題?

0

另一種選擇是使用隨機播種散列函數並對其進行排序。

檢索表格的最大和最小ids,並使用PHP的rand()函數生成最大值和最小值之間的隨機數。

然後使用該號碼到種子你散列函數.Assume {鹽}在SQL指由PHP

SELECT image FROM table 
WHERE image != '' 
ORDER BY MOD(ABS({salt}-id), MOD({salt}, 10)), ABS({salt}-id)); 

你可以優化比特執行所述MOD產生的隨機整數({鹽},10)在PHP中計算並在查詢中傳遞值。

0

如果行大小不是很大,我只會選擇50行並在應用程序中保留一個隨機列表中的12行。是的,這意味着你扔掉了80%的選定行。當你說話的時候,有50%是真的是犯罪嗎?這是SQL不擅長的事情。