2011-11-07 76 views
3

我有一個問題,這個查詢....或者,沒有像我會很快。目前,'marketingDatabase'表格大約有11萬行,但在下個月內,它可能會接近10萬行,到3月份可能增長到50萬。優化隨機記錄查詢

我知道使用ORDER BY RAND()是不是要走的路,但它是我已經得到了工作的唯一的東西。我試過其他的東西,但是第一個WHERE語句似乎把我拋棄了。我使用的是PHP,所以我也可以在PHP中處理其中的一些。

什麼是最好的方法,該查詢,從適合在WHERE語句行選擇一個隨機行?

這裏的查詢:

SELECT id 
FROM `marketingDatabase` 
WHERE do_not_call != 'true' 
    AND status = 'Pending' 
    AND install_id = 'AN ID HERE' 
    AND NOT EXISTS(
    SELECT recordID 
    FROM reminders rem 
    WHERE rem.id = marketingDatabase.id 
) 
ORDER BY rand() 
LIMIT 1 

如何使這項工作更有什麼想法?我只需要一個隨機的'身份證'。

+0

的[MySQL的可能重複:替代品以ORDER BY蘭德()](http://stackoverflow.com/questions/1823306/mysql-alternatives-to-order-by-rand) –

回答

3

首先,看看我們是否可以優化查詢一點:

SELECT `m`.`id` 
FROM `marketingDatabase` AS `m` 
    LEFT JOIN `reminders` AS `r` ON (`r`.`id` = `m`.`id`) 
WHERE 
    `m`.`do_not_call` != 'true' 
    AND `m`.`status` = 'Pending' 
    AND `m`.`install_id` = 'AN ID HERE' 
    AND `r`.`id` IS NULL 
ORDER BY 
    rand() 
LIMIT 1 

注:這只是一個想法,並沒有在野外進行了測試。

爲什麼不能計算可能的記錄數量,然後使用PHP從該計數中查找一個隨機行數,然後重新找到它。

$rowCount = 0; 

$rowCountSql = "SELECT COUNT(*) AS `rowcount` 
    FROM `marketingDatabase` AS `m` 
    LEFT JOIN `reminders` AS `r` ON (`r`.`id` = `m`.`id`) 
    WHERE 
    `m`.`do_not_call` != 'true' 
    AND `m`.`status` = 'Pending' 
    AND `m`.`install_id` = 'AN ID HERE' 
    AND `r`.`id` IS NULL"; 

if($rowCountRes = mysql_query($rowCountSql) 
    && mysql_num_rows($rowCountRes) 
    && $r = mysql_fetch_assoc($rowCountRes)) 
    $rowCount = $r['rowcount']; 

$oneRow = false; 

$oneRowSql = "SELECT `m`.`id` AS `rowid` 
    FROM `marketingDatabase` AS `m` 
    LEFT JOIN `reminders` AS `r` ON (`r`.`id` = `m`.`id`) 
    WHERE 
    `m`.`do_not_call` != 'true' 
    AND `m`.`status` = 'Pending' 
    AND `m`.`install_id` = 'AN ID HERE' 
    AND `r`.`id` IS NULL 
    LIMIT ".(int) $rowCount.", 1"; 

if($oneRowRes = mysql_query($rowCountSql) 
    && mysql_num_rows($oneRowRes) 
    && $r = mysql_fetch_assoc($oneRowRes)) 
    $oneRow = $r['rowid']; 

這可能證明有沒有性能優勢,但我只是想我會把它在那裏,看是否有更多我瞭解到的同事能更好的IT。

以上的進一步勘探(我將考驗,如果我有訪問數據庫的...)

SELECT `m`.`id` AS `rowid` 
    FROM `marketingDatabase` AS `m` 
    LEFT JOIN `reminders` AS `r` ON (`r`.`id` = `m`.`id`) 
    WHERE 
    `m`.`do_not_call` != 'true' 
    AND `m`.`status` = 'Pending' 
    AND `m`.`install_id` = 'AN ID HERE' 
    AND `r`.`id` IS NULL 
    LIMIT (FLOOR(RAND() * (
    SELECT COUNT(*) AS `rowcount` 
    FROM `marketingDatabase` AS `m` 
     LEFT JOIN `reminders` AS `r` ON (`r`.`id` = `m`.`id`) 
    WHERE 
     `m`.`do_not_call` != 'true' 
     AND `m`.`status` = 'Pending' 
     AND `m`.`install_id` = 'AN ID HERE' 
     AND `r`.`id` IS NULL))) , 1 

只是一個想法...

+1

@ user969352,我有完全相同的查詢作爲頂部的盧卡斯... ...只有另外沒有具體說明,通過使用粒度最小的索引作爲關鍵字的第一部分來優化查詢...在這種情況下,我將在(Install_ID,Status,Do_Not_Call)上創建索引。 – DRapp

0

我們遇到了同樣的問題,您現在面臨的問題是,行數太多,rand()的順序實際上導致連接掛起並拋出白頁,所以我們必須提出不同的解決方案。我們採取了

一種方案是在1000組塊了IDS,扔緩存,然後我們會隨機我們選擇哪一組,然後隨機選擇其中id列組。

我們還每天一次向平面文件寫入一個隨機ID樣本,並從中讀取數字,但我相信我們已從以前的緩存解決方案的解決方案中移開。

只是一些想法。