newid () / order by funzionerà, ma sarà molto costoso per grandi serie di risultati perché deve generare un ID per ogni riga e quindi ordinarle.
TABLESAMPLE () è buono dal punto di vista delle prestazioni, ma otterrai un raggruppamento dei risultati (verranno restituite tutte le righe di una pagina).
Per un campione casuale vero con prestazioni migliori, il modo migliore è filtrare le righe in modo casuale. Ho trovato il seguente esempio di codice nell'articolo della documentazione in linea di SQL Server Limitazione dei set di risultati tramite TABLESAMPLE :
Se desideri davvero un campione casuale di singole righe, modifica la query per filtrare le righe in modo casuale, anziché utilizzare TABLESAMPLE. Ad esempio, la query seguente utilizza la funzione NEWID per restituire circa l'uno percento delle righe della tabella Sales.SalesOrderDetail:
SELECT * FROM Sales.SalesOrderDetail
WHERE 0.01 >= CAST(CHECKSUM(NEWID(),SalesOrderID) & 0x7fffffff AS float)
/ CAST (0x7fffffff AS int)
La colonna SalesOrderID è inclusa nell'espressione CHECKSUM in modo che NEWID () valuti una volta per riga per ottenere il campionamento su base per riga. L'espressione CAST (CHECKSUM (NEWID (), SalesOrderID) e 0x7fffffff AS float / CAST (0x7fffffff AS int) restituisce un valore float casuale compreso tra 0 e 1.
Quando eseguito contro una tabella con 1.000.000 di righe, ecco i miei risultati:
SET STATISTICS TIME ON
SET STATISTICS IO ON
/* newid()
rows returned: 10000
logical reads: 3359
CPU time: 3312 ms
elapsed time = 3359 ms
*/
SELECT TOP 1 PERCENT Number
FROM Numbers
ORDER BY newid()
/* TABLESAMPLE
rows returned: 9269 (varies)
logical reads: 32
CPU time: 0 ms
elapsed time: 5 ms
*/
SELECT Number
FROM Numbers
TABLESAMPLE (1 PERCENT)
/* Filter
rows returned: 9994 (varies)
logical reads: 3359
CPU time: 641 ms
elapsed time: 627 ms
*/
SELECT Number
FROM Numbers
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), Number) & 0x7fffffff AS float)
/ CAST (0x7fffffff AS int)
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
Se riesci a cavartela usando TABLESAMPLE, ti darà le migliori prestazioni. Altrimenti usa il metodo newid () / filter. newid () / ordina per dovrebbe essere l'ultima risorsa se si dispone di un set di risultati di grandi dimensioni.