Acabo de descubrir la cláusula TABLESAMPLE
pero, sorprendentemente, no devuelve el número de filas que he especificado.TABLESAMPLE devuelve el número de filas incorrecto?
La tabla que he usado tiene ~ 14M filas y quería una muestra arbitraria de 10000 filas.
select * from tabData TABLESAMPLE(10000 ROWS)
No obtengo 10000 sino un número diferente cada vez que lo ejecuto (entre 8000 y 14000).
¿Qué está pasando aquí, he entendido mal el propósito previsto de TABLESAMPLE
?
Editar:
David's link lo explica bastante bien.
Esto devuelve siempre 10000 filas más o menos al azar de una manera eficiente:
select TOP 10000 * from tabData TABLESAMPLE(20000 ROWS);
y la opción REPEATABLE
ayuda a obtener siempre el mismo (a menos que los datos han cambiado)
select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS) REPEATABLE(100);
ya que quería saber si es más costoso usar TABLESAMPLE
con una gran cantidad de filas para asegurar (?) que obtengo el número de fila correcto, lo he medido;
1.loop (20 veces):
select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS);
(9938 row(s) affected)
(10000 row(s) affected)
(9383 row(s) affected)
(9526 row(s) affected)
(10000 row(s) affected)
(9545 row(s) affected)
(9560 row(s) affected)
(9673 row(s) affected)
(9608 row(s) affected)
(9476 row(s) affected)
(9766 row(s) affected)
(10000 row(s) affected)
(9500 row(s) affected)
(9941 row(s) affected)
(9769 row(s) affected)
(9547 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(9478 row(s) affected)
First batch(only 10000 rows) completed in: 14 seconds!
2.loop (20 veces):
select TOP 10000 * from tabData TABLESAMPLE(10000000 ROWS);
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
Second batch(max rows) completed in: 13 seconds!
3.loop: counterscheck con 100% filas aleatorios usando ORDER BY NEWID() :
select TOP 10000 * from tabData ORDER BY NEWID();
(10000 row(s) affected)
cancelado después de una ejecución que duró 23 minutos
Conclusión:
Así sorprendentemente el enfoque con una cláusula de TOP
exacta y un gran número de TABLESAMPLE
es no más lento. Por lo tanto, es una alternativa muy eficiente a ORDER BY NEWID()
si no importa que las filas no sean aleatorias por fila sino por nivel de página (cada página de 8K para la tabla tiene un valor aleatorio).
La opción repetible no ayuda a obtener las 10000 filas. Garantizará que obtengo el mismo número cada vez que se ejecuta la consulta (los datos de la unidad no han cambiado). De todos modos, el artículo lo explica muy bien. Puedo combinarlo con una cláusula 'TOP' (por ejemplo, 10000) para obtener casi 10000 filas. Gracias. –
Tampoco TOP si el resultado es * menos * que el número TABLESAMPLE. –
@David: De hecho, puede obtener el número exacto con TABLESAMPLE: 'seleccione TOP 10000 * de tabData TABLESAMPLE (20000 ROWS);'. Edité mi respuesta en consecuencia. –