2011-09-17 115 views
9

我不知道如何從一個組成員的隨機數,但我不知道什麼是做到這一點的最佳方式,我覺得ORDER BY RAND()是不是最好的選擇,因爲一組,可有超過10萬名會員,執行這種類型的查詢可能會非常緩慢。獲取隨機記錄與學說

我發現這種方式使用SQL做,但我不知道該怎麼辦的DQL同樣的事情:How can i optimize MySQL's ORDER BY RAND() function?

+1

可能重複[如何隨機選擇教義](http://stackoverflow.com/questions/10762538/how-to-select-randomly-with-doctrine) –

回答

0

我不知道的任何方式從ORDER BY RAND()「有效」教義。在你的情況下,最好的辦法可能是首先獲得主鍵,將這些鍵洗牌,然後在IN語句中使用它們。

你也可以添加一個緩存層放在哪裏(的子集)從第一個查詢鍵,尤其是如果你有很多的記錄,所以爲了避免重複,每次上的鍵查詢。

4

您可以使用您發現的查詢,以便通過本地sql查詢高效地檢索N個隨機記錄的ID,然後執行原則查詢以便通過使用dql的WHERE IN(...)來獲取對象。

例子:

// fetch $randomIds via native sql query using $em->getConnection()->... methods 
// or from a memory based cache 

$qb = $em->createQueryBuilder('u'); 

$em->createQuery(' 
    SELECT u 
    FROM Entity\User 
    WHERE ' . $qb->expr()->in('u.id', $randomIds) . ' 
'); 

如果從緩存中獲取隨機ID的同一策略適用(如redis,也許使用SRANDMEMBER) - 首先提取的標識,並通過WHERE IN獲取實體。

你只需要確保你的緩存ID在與數據庫同步(刪除ID從數據庫和緩存等,去除)

+0

我有一個觀察。通過使用'$ em-> getConnection() - > ...'或通過'$ em-> createQuery('... SQL查詢...')'通過本地sql查詢獲取id不同您? – JeanValjean

12

如下爲了不會降低性能我一般做:

//Retrieve the EntityManager first 
$em = $this->getEntityManager(); 

//Get the number of rows from your table 
$rows = $em->createQuery('SELECT COUNT(u.id) FROM AcmeUserBundle:User u')->getSingleScalarResult(); 

$offset = max(0, rand(0, $rows - $amount - 1)); 

//Get the first $amount users starting from a random point 
$query = $em->createQuery(' 
       SELECT DISTINCT u 
       FROM AcmeUserBundle:User u') 
->setMaxResults($amount) 
->setFirstResult($offset); 

$result = $query->getResult(); 

當然,$amount用戶對象,你會檢索是連續的(即第i個,第(i + 1)個,...,(我+ $amount)個),但通常是需要隨機抽取一兩個實體,而不是整個列表。因此,我認爲這是一個有效的選擇。

+0

您也可以使用自定義數字函數庫或DoctrineExtensions庫作爲[備用](http://digitalfortress.tech/php/get-random-rows-in-doctrine/)。 –