2011-02-12 17 views
33

Sé que si me funciono con esta pregunta"order by newid()" - ¿Cómo funciona?

select top 100 * from mytable order by newid() 

obtendrá 100 registros aleatorios de mi mesa.

Sin embargo, estoy un poco confundido sobre cómo funciona, ya que no veo newid() en la lista select. ¿Alguien puede explicar? ¿Hay algo especial sobre newid() aquí?

+0

Tenga en cuenta que esta es una manera lenta para obtener 100 entradas al azar a menos que el servidor reconoce db esto como un patrón conocido para optimizar. – CodesInChaos

+0

También es solo pseudoaleatorio. Si necesita aleatoriedad verdadera para la seguridad, nunca use este método. –

+2

Las columnas en su cláusula 'ORDER BY' no necesitan aparecer en su cláusula' SELECT' en SQL Server. – Gabe

Respuesta

30

Sé lo que hace NewID(), solo estoy tratando de entender cómo ayudaría en la selección aleatoria. ¿Es que (1) la instrucción de selección seleccionará todo, desde mitabla, (2) para cada fila seleccionada, tachuela en un uniqueidentifier generada por NewID(), (3) ordenar las filas por esta uniqueidentifier y (4) elige el top 100 de de la lista ordenada?

Sí. esto es casi exactamente correcto (excepto que no necesariamente tiene que ordenar todas las filas). Puede verificar esto mirando el plan de ejecución real.

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID() 

El operador de computación escalar agrega la columna NEWID() sucesivamente para cada fila (2.506 en la tabla de consulta en mi ejemplo), entonces las filas de la tabla se ordenan por esta columna con el top 100 seleccionado.

SQL Server no necesita realmente para ordenar todo el conjunto de las posiciones 100 hacia abajo por lo que utiliza un operador de TOP N tipo que intenta llevar a cabo toda la operación de ordenación en la memoria (for small values of N)

Plan

+0

¡Entendido! Y sí, tienes razón: una vez que haya determinado las 100 filas superiores de todo el conjunto, no hay necesidad de ordenar el resto. –

4

como MSDN dice:

NewID() Crea un valor único del tipo uniqueidentifier.

y su tabla estará ordenada por estos valores aleatorios.

+1

Gracias. Sé lo que hace NewID(), solo trato de entender cómo ayudaría en la selección aleatoria. ¿Es que [1] la instrucción select seleccionará TODO de mytable, [2] para cada fila seleccionada, vire en un identificador único generado por NewID(), [3] ordene las filas por este uniqueidentifier y [4] elija la parte superior 100 de la lista ordenada? –

10

En general funciona así:

  • Todas las filas de mitabla es "bucle"
  • NEWID() se ejecuta para cada fila
  • Las filas se ordenan según el número al azar de NEWID()
  • 100 primera fila se seleccionan
6

El La clave aquí es la función NEWID, que genera un identificador global único (GUID) en la memoria para cada fila. Por definición, el GUID es único y bastante aleatorio; entonces, cuando ordena por ese GUID con la cláusula ORDER BY, obtiene un orden aleatorio de las filas en la tabla. Tomando el 10 por ciento superior (o el porcentaje que desee) le dará un muestreo aleatorio de las filas en la tabla.

Se propone la consulta NEWID; es simple y funciona muy bien para tablas pequeñas. Sin embargo, la consulta NEWID tiene un gran inconveniente cuando la usa para tablas grandes. La cláusula ORDER BY hace que todas las filas de la tabla se copien en la base de datos tempdb, donde se ordenan. Esto ocasiona dos problemas: La operación de clasificación generalmente tiene un alto costo asociado. La ordenación puede usar muchas E/S de disco y puede funcionar durante mucho tiempo. En el peor de los casos, tempdb puede quedarse sin espacio. En el mejor de los casos, tempdb puede ocupar una gran cantidad de espacio en el disco que nunca se recuperará sin un comando de contracción manual. Lo que necesita es una forma de seleccionar filas al azar que no usará tempdb y que no será mucho más lenta a medida que la tabla se agranda. He aquí una nueva idea sobre cómo hacerlo:

SELECT * FROM master..spt_values 
    WHERE (ABS(CAST(
    (BINARY_CHECKSUM(*) * 
    RAND()) as int)) % 100) < 10 

La idea básica detrás de esta consulta es que queremos generar un número aleatorio entre 0 y 99 para cada fila de la tabla, y luego elegir todos los filas cuyo número aleatorio es menor que el valor del porcentaje especificado. En este ejemplo, queremos aproximadamente el 10 por ciento de las filas seleccionadas al azar; Por lo tanto, elegimos todas las filas cuyos números aleatorios es inferior a 10.

+0

Buena idea, pero solo funcionaría si está intentando hacer un 'TOP N%'. Si haces un 'TOP 500' normal, por ejemplo, no funcionará. A menos que tengas un camino diferente a eso (que me encantaría escuchar). Gracias. –

1

uso select top 100 randid = newid(), * from mytable order by randid que se aclararán a continuación ..