2009-03-16 13 views
14

Ho una tabella enorme di> 10 milioni di righe. Ho bisogno di prendere in modo efficiente un campionamento casuale di 5000 da esso. Ho alcuni costringenti che riducono le righe totali che sto cercando di apprezzare 9 millon.Seleziona campionamento casuale da sqlserver rapidamente

Ho provato a utilizzare l'ordine di NEWID(), ma quella query richiederà troppo tempo poiché deve eseguire una scansione tabella di tutte le righe.

C'è un modo più veloce per farlo?

+0

stai usando un po 'di php/asp/qualsiasi cose del genere? – Skuta

+2

Perché dovrebbe importare? Certamente non voglio il livello dell'app per farlo! –

risposta

19

Se è possibile utilizzare un campione pseudo-casuale e siete su SQL Server 2005/2008, allora date un'occhiata a TABLESAMPLE. Per esempio, un esempio da SQL Server 2008/AdventureWorks 2008, che funziona in base righe:

USE AdventureWorks2008; 
GO 


SELECT FirstName, LastName 
FROM Person.Person 
TABLESAMPLE (100 ROWS) 
WHERE EmailPromotion = 2; 

Il problema è che non è esattamente TABLESAMPLE casuale in quanto genera un dato numero di righe di ogni pagina fisica. Potresti non recuperare esattamente 5000 righe a meno che non ti limiti anche con TOP. Se si utilizza SQL Server 2000, è necessario generare una tabella temporanea che corrisponda alla chiave primaria o che dovrà essere eseguita utilizzando un metodo che utilizza NEWID().

+2

Wrong, tablesample funziona selezionando numero appropriato di pagine e quindi restituire tutte le righe trovate su quelle pagine.Il punto intero è evitare di colpire tutte le pagine che reggono il tavolo – friism

+0

Scusa, hai ragione. Leggi l'algoritmo errato. Determina il numero di righe e poi seleziona il intera pagina o non per ottenere il numero approssimativo. –

+0

Sidenote: stai applicando la clausola where al campione già troncato.Quindi non aspettarti che restituisca le righe corrispondenti in tutte le circostanze. –

4

Sì, TABLESAMPLE è tuo amico (si noti che non è casuale nel senso statistico del termine): Tablesample at msdn

+0

Stiamo usando sqlserver 2005, ma il nostro livello di compatibilità del database è a 80, quindi nessun tablesample. :(altre idee? –

+0

seleziona * dai clienti ordina da newid() – Albert

8

Avete guardato in utilizzando la clausola TABLESAMPLE?

Ad esempio:

select * 
from HumanResources.Department tablesample (5 percent) 
+0

Questo problema era tale che Microsoft doveva realizzare questa implementazione nativa di TABLESAMPLE ed è la più stabile ed efficiente in tutti gli scenari –

6

SQL Server 2000 Solution, per quanto riguarda Microsoft (invece di lenta NEWID() su tavoli più grandi):

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

Il team di SQL Server di Microsoft si rese conto che non essere in grado di prendere campioni casuali di le righe erano facilmente un problema comune in SQL Server 2000; così, il team ha risolto il problema in SQL Server 2005 introducendo la clausola TABLESAMPLE. Questa clausola seleziona un sottoinsieme di righe per scegliendo le pagine di dati casuali e restituendo tutte le righe su quelle pagine . Tuttavia, per quelli di noi che hanno ancora prodotti in esecuzione su SQL Server 2000 e necessitano di retrocompatibilità, o che hanno veramente bisogno della casualità a livello di riga , la query BINARY_CHECKSUM è una soluzione efficace .

spiegazione può essere trovata qui: http://msdn.microsoft.com/en-us/library/cc441928.aspx

Problemi correlati