2011-12-09 22 views
8

He mirado alrededor y no parece haber ninguna manera fácil de hacerlo. Casi parece que es más fácil simplemente capturar un subconjunto de registros y hacer toda la asignación al azar en el código (perl). Los métodos que he visto en línea parecen estar más orientados a cientos de miles, pero ciertamente no a millones.Seleccione rápidamente ID aleatorio de la tabla mysql con millones de registros no secuenciales

La tabla con la que estoy trabajando tiene 6 millones de registros (y sigue creciendo), los ID se incrementan automáticamente, pero no siempre se almacenan en la tabla (sin gapless).

He intentado hacer la consulta LIMIT 1 que se ha recomendado, pero la consulta tarda mucho en ejecutarse: ¿hay una forma rápida de hacerlo, dado que hay lagunas en el registro? No puedo tomar el máximo y aleatorizar sobre el rango.

Actualización:

Una idea que tenía tal vez era para agarrar el máximo, de forma aleatoria un límite basado en el máximo, y luego tomar un alcance de 10 registros de random_limit_1 a random_limit_2 y después de tomar el primer registro encontrado en ese rango

O si conozco el máximo, ¿hay alguna manera de que pueda elegir decir el 5to registro de la tabla, sin tener que saber qué ID es? Entonces solo agarrando la identificación de ese registro.

Actualización:

Esta consulta es algo más rápido-ish. Todavía no lo suficientemente rápido =/

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

¿Qué quiere decir con 'non-gapless'? Que hay lagunas? –

+0

Sí. exactamente eso =] – qodeninja

+1

bastante seguro nodebunny significa un índice de autoincrement típico que ha tenido algunas filas borradas en el pasado ... –

Respuesta

5

Sí, parece buena idea:

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 
; 

pueden cambiar 1.000 a 10.000 o lo que sea necesario para escalar .. .

EDIT: también se podría tratar esto:

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

divide a lo largo de diferentes líneas ...

EDIT 2:

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

Esta es probablemente la manera más rápida:

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

por desgracia, las variables no se pueden utilizar en cláusula de límite por lo que tendría que usar una consulta dinámica, ya sea escribiendo la cadena de consulta en el código, o usando PREPARE y EXECUTE. Además, el límite n, 1 aún requiere escanear n elementos en la tabla, por lo que es aproximadamente el doble de rápido que el segundo método mencionado anteriormente en promedio. (Aunque probablemente sea más uniforme y garantice que siempre se encontrará una fila coincidente)

+0

Ejecuté esta consulta pero me devolvió un conjunto vacío. – qodeninja

+0

Si hay lagunas de más de 1000 registros, podría suceder ... ¿Cómo es la distribución de sus identificaciones? –

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

Ok, esto es lento. Si busca ORDER BY RAND() MYSQL, encontrará muchos resultados que indican que esto es muy lento y este es el caso. Hice un poco de investigación y me encontré con esta alternativa MySQL rand() is slow on large datasets espero que esto es mejor

+0

Eres demasiado rápido ........ +1 – Jomoos

+0

Sí, lo intenté, pero se necesitan FOREVERS para que la consulta se ejecute incluso en el límite 1. – qodeninja

+0

la consulta en ese enlace SELECCIONE t.id FROM table t JOIN (SELECT (FLOOR (max (id) * rand())) como maxid FROM table) como tt en t.id> = tt.maxid LIMIT 1 es un poco más rápido - aún demasiado lento =/ – qodeninja

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

intente ejecutar esta consulta en 6 millones de registros. lleva una eternidad correr – qodeninja

Cuestiones relacionadas