Published on

August 16, 2023

Generando filas aleatorias en SQL Server

Cuando trabajamos con SQL Server, puede haber momentos en los que necesitemos recuperar registros aleatorios o una muestra de filas aleatorias de una tabla. Sin embargo, a diferencia de otras bases de datos, SQL Server no tiene una función incorporada para devolver resultados aleatorios directamente. En este artículo, exploraremos varias técnicas para lograr esto y analizaremos en profundidad su rendimiento y características de aleatoriedad.

Métodos nativos en SQL Server

Uno de los métodos más simples para recuperar filas aleatorias en SQL Server es utilizando la función NEWID(). Esta función genera un GUID único para cada fila y nos permite seleccionar las primeras filas después de ordenarlas por él. Aquí tienes un ejemplo:

SELECT TOP 10 *
FROM table
ORDER BY NEWID();

Sin embargo, este método puede ser altamente ineficiente y no escala bien para tablas grandes. Algunas desventajas incluyen:

  • La función NEWID() escaneará toda la tabla, asignando un ID único a cada fila. Esto puede ser extremadamente ineficiente para tablas grandes.
  • El proceso de ordenación consume una cantidad significativa de espacio temporal en disco y puede llevar mucho tiempo completarse.
  • El costo de la consulta aumenta exponencialmente con el tamaño de la tabla al usar ORDER BY NEWID().

Aprovechando TABLESAMPLE

SQL Server proporciona la cláusula TABLESAMPLE, que nos permite recuperar una muestra estadística de filas de una tabla. Aquí tienes un ejemplo:

SELECT *
FROM table
TABLESAMPLE (10 PERCENT);

Aunque esto puede parecer una forma eficiente de obtener filas aleatorias, hay algunas advertencias a tener en cuenta:

  • TABLESAMPLE no muestrea filas aleatorias. En su lugar, selecciona páginas de datos aleatorias de 8KB y devuelve todas las filas en esas páginas.
  • Si la tabla tiene un índice agrupado ordenado por una columna como ID, las filas muestreadas podrían pertenecer a un rango particular de IDs, sesgando los resultados.
  • TABLESAMPLE se aplica antes de WHERE, JOIN u otros filtros, por lo que es posible que sea necesario filtrar aún más las filas muestreadas.

En general, TABLESAMPLE debe usarse con cuidado al generar muestras aleatorias de una tabla.

Alternativas para la selección de filas aleatorias

Otro enfoque para obtener filas aleatorias es filtrar en función de una condición aleatoria utilizando la función CHECKSUM. Aquí tienes un ejemplo:

SELECT *
FROM table
WHERE ABS(CHECKSUM(NEWID())) % 100 < 10; -- muestra aleatoria del 10%

Este método funciona bien ya que CHECKSUM está optimizado en SQL Server y solo requiere un índice o un escaneo de tabla. Algunos consejos para utilizar este método de manera efectiva incluyen:

  • Asegúrate de que haya un índice en los campos que se están verificando para evitar un escaneo completo de la tabla.
  • Considera utilizar NEWID() o CAST(Column AS VARBINARY) dentro de CHECKSUM para una mejor distribución, ya que CHECKSUM(Column) solo puede estar sesgado.
  • Utiliza múltiples condiciones de CHECKSUM con OR y diferentes porcentajes de filtro para reducir duplicados en muestras más grandes.

Para recuperar una sola fila aleatoria, se puede utilizar un enfoque híbrido que combine TABLESAMPLE y el ordenamiento de NEWID():

SELECT TOP 1 *
FROM table
TABLESAMPLE (100 ROWS)
ORDER BY NEWID();

Este enfoque minimiza el número de filas ordenadas al limitar el ordenamiento de NEWID() al subconjunto muestreado. Con una muestra lo suficientemente grande, se preserva la aleatoriedad al tiempo que se mejora el rendimiento.

Conclusión

SQL Server ofrece múltiples alternativas para recuperar filas aleatorias, cada una con sus propias implicaciones de rendimiento. El uso de filtrado basado en CHECKSUM o la selección de valores de columna indexados tiende a funcionar mejor en la mayoría de los casos. El enfoque híbrido de TABLESAMPLE y NEWID() también se ejecuta rápidamente al recuperar una sola fila aleatoria. Si tienes alguna otra técnica para generar filas aleatorias en SQL Server, no dudes en compartirla conmigo a través de LinkedIn.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.