2011-09-17 21 views
9

Mi chiedo come ottenere un numero casuale di membri da un gruppo, ma non so qual è il modo migliore per farlo e penso che lo ORDER BY RAND() non sia la migliore alternativa, poiché un gruppo può avere più di 100.000 membri, l'esecuzione di questo tipo di query potrebbe essere molto lenta.Ottieni record casuali con Doctrine

ho trovato questo modo per rendere l'utilizzo di SQL, ma non so come fare la stessa cosa in DQL: How can i optimize MySQL's ORDER BY RAND() function?

+1

Possibile duplicato di [Come selezionare in modo casuale con la doctrina] (http://stackoverflow.com/questions/10762538/how-to-select-randomly-with-doctrine) –

risposta

0

Io non sono a conoscenza di alcun modo per ORDER BY RAND() "in modo efficace" da Dottrina. Nella tua situazione, la cosa migliore è probabilmente ottenere le chiavi primarie, mescolare queste chiavi e utilizzarle all'interno di un'istruzione IN.

È inoltre possibile aggiungere un livello di memorizzazione nella cache in cui inserire (un sottoinsieme di) le chiavi della prima query, soprattutto se si dispone di molti record, in modo da evitare di ripetere la query sui tasti ogni volta.

4

È possibile utilizzare la query trovata per recuperare in modo efficiente gli ID di N record casuali tramite una query sql nativa, quindi eseguire una query di dottrina per recuperare gli oggetti tramite un WHERE IN(...) utilizzando dql.

Esempio:

// 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) . ' 
'); 

La stessa strategia si applica se si recupera ids casuali da una cache (come redis, magari usando SRANDMEMBER) - prima prendere gli ID, quindi recuperare i soggetti tramite un WHERE IN.

Devi solo per assicurarsi che il proprio ID di cache sono in sincronia con il database (IDS eliminati vengono rimossi dal database e dalla cache, ecc)

+0

Ho un'osservazione. Il recupero degli ID tramite query sql nativa usando '$ em-> getConnection() -> ...' o tramite '$ em-> createQuery ('... SQL query ...')' non è lo stesso per tu? – JeanValjean

12

Per non diminuire le prestazioni sono generalmente come segue:

//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(); 

Naturalmente, gli utenti $amount oggetto si recuperano sono consecutivi (cioè il i-esimo, (i + 1) -esimo, ..., (i + $amount) -esimo), ma di solito c'è la necessità di prendere una o due entità a caso, non l'intera lista. Quindi, penso che questa sia un'alternativa efficace.

+0

È inoltre possibile utilizzare un valore numerico personalizzato fn o DoctrineExtensions Lib come [alternativo] (http://digitalfortress.tech/php/get-random-rows-in-doctrine/). –

Problemi correlati