2010-03-31 9 views
6

che è più efficiente (quando si gestiscono oltre 100K record):MySQL PHP vs durante il recupero di un elemento casuale

A. Mysql

SELECT * FROM user ORDER BY RAND(); 

naturalmente, dopo che avrei già avere tutte le campi da quel record.

B. PHP

uso memcached di avere $ cache_array contenere tutti i dati da "SELECT id_user ORDINAZIONE utente BY id_user" per 1 ora o giù di lì ... e poi:

$ id = array_rand ($ cache_array);

naturalmente, dopo che devo fare una chiamata MySQL con:

SELECT * FROM user WHERE id_user = $id; 

così ... che è più efficiente? A o B?

+0

duplicati: http://stackoverflow.com/questions/1823306/alerternative-to-mysql-order-by-rand –

+2

@OMG Ponies: E 'simile, ma non una vittima.Non sta chiedendo il modo migliore per implementarlo in Mysql, sta chiedendo un confronto tra due metodi. – ryeguy

+0

Secondo questo grafico (vedi link alla fine), ~ 100K ordinati per RAND() è al secondo. Sono curioso di vedere se PHP (molto meno .NET o J2EE) fornirà prestazioni simili: http://stuff.dasprids.de/images/benchmark-random-row-full.png –

risposta

8

Il modo corretto di rispondere a questo tipo di domande è di fare un punto di riferimento. Esegui un'implementazione rapida e sporca in ogni caso, quindi esegui test di benchmark per determinare quale sia la migliore.

Detto questo, ORDER BY RAND() è noto per essere lento perché è impossibile per MySQL utilizzare un indice. MySQL eseguirà fondamentalmente la funzione RAND() una volta per ogni riga nella tabella e quindi ordinerà le righe in base a ciò che è tornato da RAND().

L'altra idea di memorizzare tutti gli user_id in memcached e quindi selezionare un elemento a caso la matrice potrebbe funzionare meglio se il sovraccarico di memcached risulta inferiore al costo di una scansione completa della tabella. Se il tuo set di dati è grande o la stoltezza è un problema, puoi comunque incorrere in problemi. Inoltre stai aggiungendo una certa complessità alla tua applicazione. Proverei a cercare un altro modo.

io ti do una terza opzione che potrebbe sovraperformare entrambi i vostri suggerimenti: selezionare una count(user_id) delle righe della tabella utente e quindi avere php generare un numero casuale compreso tra 0 e il risultato di count(user_id) meno 1, inclusiva. Quindi fai un SELECT * FROM user LIMIT 1 OFFSET random-number-generated-by-php;.

Anche in questo caso, il modo corretto per rispondere a questi tipi di domande è il benchmark. Qualcos'altro è speculazione.

+0

+1 per la terza opzione –

+0

questo funzionerebbe alla grande, tranne che ho dimenticato di specificare che i record che possono essere selezionati devono essere filtrati con un WHERE flg_pic = 1. Se faccio un conteggio (id_user) verrebbero considerati anche i record che hanno flg_pic = 0: s – andufo

+0

@andufo: Questo non è proprio un problema. Si può fare 'SELECT COUNT (user_id) FROM user WHERE flg_pic = 1;' e quindi 'SELECT * FROM user WHERE flg_pic = 1 LIMIT 1 OFFSET random-number-generated-by-php;'. – Asaph

4

Il primo è incredibilmente lento perché

MySQL crea una tabella temporanea con tutte le righe risultanti e assegna ogni uno di essi un indice ordinamento casuale. I risultati vengono quindi ordinati e restituito .

È stato elaborato di più su this blog post.

0
$random_no = mt_rand(0, $total_record_count); 

$query = "SELECT * FROM user ORDER BY __KEY__ LIMIT {$random_no}, 1"; 
Problemi correlati