2011-12-09 13 views
8

Mi sono guardato intorno e non sembra esserci un modo semplice per farlo. Sembra quasi che sia più semplice afferrare un sottoinsieme di record e fare tutto il codice casuale (perl). I metodi che ho visto online sembrano essere più orientati al massimo a centinaia di migliaia, ma certamente non a milioni.Seleziona rapidamente ID casuale dalla tabella mysql con milioni di record non sequenziali

La tabella con cui sto lavorando ha 6 milioni di record (e in crescita), gli ID sono autoincrementati, ma non sempre memorizzati nella tabella (non-gapless).

Ho provato a eseguire la query LIMIT 1 che è stata consigliata, ma la query impiega per sempre l'esecuzione - c'è un modo rapido per farlo, dato che ci sono lacune nel record? Non posso prendere il massimo e randomizzare oltre l'intervallo.

Aggiornamento:

Un'idea che avevo forse è stato quello di prendere il massimo, casuale un limite in base al massimo, e poi prendete una serie di 10 record da random_limit_1 a random_limit_2 e poi prendendo il primo record trovato in quel raggio.

Oppure, se conosco il limite massimo, c'è un modo in cui posso semplicemente dire il quinto record del tavolo, senza dover sapere quale ID è. Quindi basta prendere l'id di quel disco.

Aggiornamento:

Questa query è in qualche modo più veloce-ish. Ancora non è abbastanza veloce =/

SELECT t.id FROM table t JOIN (SELECT(FLOOR(max(id) * rand())) as maxid FROM table) as tt on t.id >= tt.maxid LIMIT 1 
+0

Cosa intendi con 'non-gapless'? Che ci sono lacune? –

+0

Sì. esattamente that =] – qodeninja

+1

piuttosto sicuro nodebunny significa un tipico indice di autoincremento che ha avuto alcune righe cancellate in passato ... –

risposta

5

Sì, idea sembra buona:

select min(ID), max(ID) from table into @min, @max; 
set @range = @max - @min; 
set @mr = @min + ((@range/1000) * (rand() * 1000)); 
select ID from table 
    where ID >= @mr and ID <= @mr + 1000 
    order by rand() 
    limit 1 
-- into @result 
; 

possono cambiare 1.000-10.000 o qualsiasi altra cosa, se necessario per scalare .. .

EDIT: si potrebbe anche provare questo:

select ID from table 
    where (ID % 1000) = floor(rand() * 1000) 
    order by rand() 
    limit 1 
; 

divide lungo linee differenti ...

EDIT 2:

See: What is the best way to pick a random row from a table in MySQL?

Questo è probabilmente il modo più veloce:

select @row := floor(count(*) * rand()) from some_tbl; 
select some_ID from some_tbl limit @row, 1; 

purtroppo, le variabili non possono essere utilizzate in clausola limite in modo da utilizzare una query dinamica, scrivendo la stringa di query nel codice o utilizzando PREPARE ed EXECUTE. Inoltre, il limite n, 1 richiede ancora la scansione di n elementi nella tabella, quindi è solo circa il doppio del secondo metodo sopra elencato in media. (Anche se è probabilmente più uniforme e garantisce sempre che una riga corrispondente sarà sempre trovata)

+0

Ho eseguito questa query ma ha restituito un set vuoto. – qodeninja

+0

Se ci sono spazi più ampi di 1000 record, ciò potrebbe accadere ... Qual è la distribuzione dei tuoi ID? –

8
SELECT * FROM TABLE ORDER BY RAND() LIMIT 1; 

Ok, questo è lento. Se cercherete ORDER BY RAND() MYSQL, troverete molti risultati che dicono che questo è molto lento e questo è il caso. Ho fatto una piccola ricerca e ho trovato questa alternativa MySQL rand() is slow on large datasets Spero che questo sia meglio

+0

Sei troppo veloce ........ +1 – Jomoos

+0

Sì, l'ho provato ma ci sono FOREVERS perché la query venga eseguita anche sul Limite 1. – qodeninja

+0

la query su quel link SELECT t.id FROM table t JOIN (SELEZIONA (FLOOR (max (id) * rand())) come max della tabella FROM) come tt su t.id> = tt.maxid LIMIT 1 è leggermente più veloce - ancora troppo lento =/ – qodeninja

0
SELECT ID 
    FROM YourTable 
    ORDER BY RAND() LIMIT 1; 
+4

prova a eseguire questa query su 6 milioni di record. ci vuole un'eternità per correre. – qodeninja

Problemi correlati