El rincón de JMACOE

Recuperando datos aleatorios de SQL Server con TABLESAMPLE

Este truco es parecido tanto a la función RAND () como a la función NEWID(). Ambos métodos son útiles, pero un problema con estos, es que dependiendo de cómo los usas puedes terminar leyendo toda la tabla entera para conseguir una distribución aleatoria de los datos. Lo bueno de esto es que estás casi seguro de que obtendrás un conjunto de registros totalmente aleatorio cada vez. Debido a la potencial sobrecarga con la lectura a través de toda la tabla ¿Existen otros métodos para recuperar datos de forma aleatoria?


En SQL Server 2005/2008 una nueva opción ha sido añadida a la cláusula FROM. Esta nueva opción es la característica TABLESAMPLE. Con la opción TAMPLESAMPLE eres capaz de obtener una muestra de un conjunto de datos de la tabla sin tener que leer toda la tabla o de tener que asignar temporalmente valores aleatorios a cada fila de datos. A primera vista esto suena muy bien, pero hay una cuantas cosas a tener en cuenta al utilizar esta nueva opción.

La forma como esto funciona es que los datos se leen en el nivel de página. A cada página de 8K de la tabla se le asigna un valor aleatorio y con base en este valor al azar y el valor que especifica el número o porcentaje de filas será determinara cuántas filas se devolverán. Según esto, cada serie puede recuperar un número totalmente diferente de filas de datos.

¿Cómo usarlo?

Para utilizar TABLESAMPLE, esta cláusula se pone después de la cláusula FROM de la siguiente manera:

Se podría pensar que la opción 1000 filas devolvería 1000 filas, pero lo que pasa es que este número se convierte en uno por ciento antes de la ejecución en función del número que ha especificado y el número aproximado de filas de la tabla. Así que una vez más no está garantizado un número exacto de filas.

Aquí hay una consulta de ejemplo la base de datos AdventureWorks.

SELECT * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS)

Aquí esta una pequeña muestra con la ejecución de la consulta anterior:

Ejecutar # # De filas
1 1288
2 658
3 806
4 1232
5 1064

Como se puede ver ninguna de estas ejecuciones regresaron 1000 filas. El número total de filas es bastante aleatorio. Para ayudar que retorne un número exacto de filas puede ayudar el  comando TOP, como la siguiente consulta:

SELECT TOP 250 * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS)

Utilizar el comando TOP con un número menor que las filas de la muestra que estamos más o menos garantizando para conseguir el número de filas que esperamos de la consulta.

Otra cosa a tener en cuenta es que si el valor de ROWS es demasiado pequeño existe la posibilidad de que no se puede obtener ningún dato de la consulta. En mis pruebas cuando estableces este valor en (100 ROWS) algunas de las ejecuciones no ha devuelto ningún dato. Así que ten esto en cuenta.

Otra cosa a tener en cuenta es que los datos son tomados página por página, no fila por fila. Por lo tanto basado en la muestra del conjunto de datos deberá ser tan diverso tanto como los datos que se almacenan en cada página de datos. Así que según nuestro ejemplo, el índice agrupado es SalesOrderID. Este valor no es tan aleatorio a lo largo de cada página de datos y por lo tanto tenemos grupos de datos que son al azar frente a un conjunto de datos completo al azar al nivel de fila.

Aquí está otra consulta para ilustrar esto.

SELECT TOP 10 * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS)

Como se puede ver abajo en las cinco ejecuciones el SalesOrderID es el mismo para todas las ejecuciones a excepción de ejecución #4. Ya que los datos se almacenan en base a SalesOrderID una muestra de sólo 10 registros no será del todo al azar.

SalesOrderID retornado
Ejecución #1 Ejecución #2 Ejecución #3 Ejecución #4 Ejecución #5
47967
47967
47967
47967
47967
47967
47967
47967
47967
47967
50208
50208
50208
50208
50208
50208
50208
50208
50208
50208
43850
43850
43850
43850
43850
43850
43850
43850
43850
43850
44311
44311
44312
44312
44312
44312
44313
44313
44313
44313
44127
44127
44127
44127
44127
44127
44127
44127
44127
44127

Además de la recuperación de datos al azar que todos podemos usar la opción REPEATABLE de manera que la consulta devuelve el mismo conjunto aleatorio de datos cada vez que ejecute la consulta. Una vez más, esto supone que sus datos no ha cambiado.

SELECT TOP 10 * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS) REPEATABLE (25)

Cuando la consulta anterior se ejecuta la muestra del conjunto de datos que se devuelve será el mismo cada vez que se ejecuta la consulta.

Esta es otra nueva opción que se puede aprovechar de SQL Server 2005/2008. A ver si este es un enfoque mejor y más rápido para la recuperación de datos al azar desde las tablas.

Lee más sobre la opción TABLESAMPLE.

Comparte y diviertete: