2013-06-04 9 views
5

Ricordo di aver letto da qualche parte che l'ordine di rand() è sbagliato e ho appena iniziato a trovarlo e ho trovato un articolo che lo dimostra. Order by rand() può essere estremamente lento con database di grandi dimensioni e la soluzione suggerita era quella di generare un numero casuale in php e selezionare in base ad esso. Il problema è che ho bisogno di verificare altri campi per restituire i miei record. Potrei anche aver cancellato alcuni vecchi record, che potrebbero anche causare un problema. Qualcuno può fornire un modo decente per selezionare alcuni record casuali da una tabella che corrisponde a determinate condizioni (ad esempio il campo paid deve essere uguale a 1)?Restituisce risultati casuali (ordine by rand())

+0

se si utilizza php, utilizzare la funzione 'shuffle'. quindi ottieni i tuoi risultati e poi mescolali nel tuo programma. –

+0

Ma cosa succede se ho restituito 100.000 risultati, non voglio recuperare tutto ciò che –

+0

@FabianBigler tirando un numero elevato di risultati in php per ottenere solo pochi è probabile che sia molto più lento del limite "order by rand()" N'. – Kevin

risposta

2

Quanto casuali avete bisogno che siano? se non avete bisogno di un super distribuzione uniforme provare questo

select min(pk_id) from my_table where pk_id > %(random_number)s and paid=1 

dove %(random_number)s è una variabile bind contenente un numero casuale 0-max(pk_id)-1 rigenerato ogni volta che si esegue la query

+0

Questa è una buona idea, ma non posso permettermi di rischiare di mostrare lo stesso insieme di risultati numerose volte. Questo dirà solo alle persone che ho un brutto sistema randomizzante. + rep though –

+0

@php_nub_qq sarà ogni volta un record diverso se si genera un nuovo numero casuale ogni volta che si esegue la query – cmd

+0

Sì, lo so, ma ho bisogno di restituire da 2 a 8 record, a cui mi riferisco come un set, e se il numero casuale deve essere max (pk_id) -8 (che imposterò come numero massimo di rand), verranno visualizzati sempre pk_id-7 e pk_id-6. E se 8 è il numero di record che ho bisogno di restituire l'ultimo 8 sarà sempre consecutivo. Non voglio eseguire 8 query separate –

7

La ragione per cui l'ordinazione da RAND() può essere lento è che stai forzando il database a ordinare effettivamente l'intera tabella prima di restituire qualsiasi cosa. Basta ridurre il carico su una singola scansione della tabella è molto più veloce (anche se ancora un po 'lento).

Questo significa che si potrebbe ottenere un pezzo di strada semplicemente evitando l'ordine:

SELECT * 
    FROM my_table 
    WHERE RAND() < 0.1 
ORDER BY RAND() 
    LIMIT 100 

Questo selezionerà circa l'1% di tutte le righe della tabella, ordinarli e restituire il top 100. Proprio nota che il problema principale qui (così come con la risposta di @ cmd) è che non puoi essere sicuro che la query restituisca qualcosa.

L'approccio sopra dovrebbe comportare un'intera scansione della tabella (per decidere quali righe utilizzare) seguita da una sorta di circa l'1% delle righe. Se hai molte righe, puoi ridurre la percentuale di conseguenza.

+0

Ho bisogno di essere sicuro che restituirò qualcosa e ho bisogno di essere sicuro che i record restituiti siano completamente casuali. Se non esiste un'opzione migliore, vorrei utilizzare il suggerimento di @ cmd ed eseguire alcune query in più. –

+0

Ma il suggerimento di @ cmd ha la stessa debolezza: non puoi essere sicuro che restituirà qualcosa. – mzedeler

+0

Perché no? Non vedo come potrebbe non restituire nulla. –

Problemi correlati