2010-10-16 38 views
6

Ho bisogno di recuperare e mostrare i dati su una pagina web il cui numero di record può variare in base ai filtri da circa 500 record a 1 milione di record.Quale sarebbe il modo migliore per recuperare circa un milione di record dal DB?

Il caching sarà utile qui perché penso che milioni di record in memoria non siano un buon pensiero. SqldataReader?

Il cercapersone è un imperativo da implementare naturalmente. Mostrare 1 milione di record è uno scenario peggiore (lo stupido All filter in casi d'uso!).

Devo utilizzare architettura connessa (SqlDataReader) o architettura disconnessa (DataSets)?

+4

sto solo cercando di capire se ci sono abbastanza ore in un giorno per sfogliare un milione di righe di dati. Diciamo 40 righe per pagina quindi 25.000 pagine richieste, diciamo che 1 minuto di navigazione per pagina sarebbe 25.000 minuti o circa 17 giorni - eeeek –

+3

Non ha senso visualizzare un milione di record se me lo chiedi. Qual è lo scenario qui? –

+0

A parte, supponendo che i tuoi record abbiano una media di 150 byte (è come un nome, una breve descrizione, un paio di interi e un paio di bool). 1 milione di record sarebbe inferiore a 150 MB. Non proprio troppo da archiviare nella cache. Tuttavia, vale la pena notare che il server del database (probabilmente SQL Server) sta già eseguendo la memorizzazione nella cache. In effetti, se query simili sono comuni e si ha molta memoria, penso che sia possibile che l'intera tabella sia in memoria. – tster

risposta

10

Prima di tutto, pensateci in questo modo: la visualizzazione di 1 milione di record non ha assolutamente senso per nessun utente. Quindi, devi pensare a ciò che l'utente si aspetta di vedere. Forse un riassunto ?! Forse impaginare i record in pagine di 25 o 50 o 100 record. Ciascuno di questi approcci non richiede di tenere in memoria 1 record M alla volta.

Inoltre, quando si esegue una query su un database SQL e si utilizza SqlDataReader, non si riceveranno tutti i record, ma il driver SQL invierà la query al server SQL, il server eseguirà la query, preparerà un set di risultati e creare un cursore forward-only sul server. Quindi il driver recupera un record alla volta, ogni volta che si chiama Read() su SqlDataReader. Il comportamento è molto simile se si utilizza LINQ to SQL che utilizza l'esecuzione posticipata. Il set di risultati non viene trasferito completamente finché (o meno) non si specifica specificamente ogni singola riga.

Quindi, una semplice query di impaginazione farà il trucco. O in altri casi una sorta di rapporto di sintesi che aggrega i dati da quei 1 milione di record di una o due pagine di dati rilevanti.

Ovviamente, se è necessario spostarsi avanti e indietro tra le pagine, è possibile che una sorta di memorizzazione nella cache abbia un senso, ma, ripensandoci, quanto spesso un utente desidera effettivamente sfogliare 1 milione di record, probabilmente mai.

Come ultima nota, se si implementa l'impaginazione, accertarsi che il metodo utilizzato per implementare l'impaginazione si basi sul server SQL che invia i dati una pagina alla volta e non legge tutti i 1 milione di record in ASP.NET e quindi impaginando la copia locale dei dati perché sarebbe molto inefficiente e lento. Ecco un esempio di una query di SQL Server che esegue l'impaginazione: SO Question #109232

+0

Bella spiegazione dettagliata. Grazie! Ma ancora una domanda: i DataSet non saranno di alcun aiuto qui? – Manish

+1

Un DataSet funziona in modo diverso. A differenza di SqlDataReader che ha un comportamento di sola andata, un DataSet deve portare tutti i dati dal server localmente prima di operare su di esso. In alcuni casi è più semplice da utilizzare, ma se la query restituisce 1 milione di record, DatSet non è la soluzione. Alla fine tutto dipende dalla query. –

1

Se il server non riesce a memorizzare nella cache 1 milione di record, come pensi che il browser Web dell'utente gestirà un milione di record di codice HTML in arrivo?

consideri paginazione (here is an example with 1 million records)

Considera anche che l'utente non vuole mai più di circa 30 a 50 record. Stai mostrando loro un livello di dettaglio troppo basso o hai bisogno di più filtri.

+0

Questo link è stato interessante. Una specie di cosa voglio Ma cosa sta usando in background ... Dataset? Vedo che il recupero è piuttosto veloce. – Manish

+0

@Manish, lo sfondo è agnostico a quella griglia. Utilizzando qualsiasi lingua è possibile connettersi a qualsiasi database. Quindi il trucco è scrivere query SQL che utilizzino gli indici correttamente in modo tale che la restituzione delle righe n-m sia veloce. – tster

3

Concordo con il resto degli utenti. la visualizzazione dei record 1M è ridicola. Tuttavia, è possibile visualizzare i primi record X e la pagina.

Il trucco è nella stored procedure facendo il recupero

ALTER PROCEDURE [dbo].[MyHugeTable_GetWithPaging] 
( 
     @StartRowIndex  int, 
     @MaximumRows  int 
) 

AS 
SET NOCOUNT ON 

Select 
    RowNum, 
    [UserName] 
From 
    (Select 
     [ID], 
     [UserName] 
     Row_Number() Over(Order By [ID] Desc) As RowNum 
     From dbo.[MyHugeTable] t) 
As DerivedTableName 
Where RowNum Between @StartRowIndex And (@StartRowIndex + @MaximumRows) 
+0

In realtà il DB è MS-SQL Server 2008. – Manish

+0

Sì, questo è quello che uso. –

+0

Bello! Interessante!! – Manish

0

io suggerisco query dinamica utilizzo con paginazione. quindi, quando fai clic su una pagina specifica, recupera i record solo per quelle pagine. Per recuperare record dal database da intervallo specifico, utilizzare la seguente query.

come questo.

Create proc Test 

@take smallint, 
@skip smallint, 
@orderBy nvarchar(20), 
@subscriptionid smallint, 


as 

DECLARE @SQLQuery AS NVARCHAR(max) 

SET @SQLQuery=' Select ROW_NUMBER() OVER (ORDER BY P.ProductId desc) as RowNum,* from product" 

set @[email protected] + ' and Subscriptionid='+CONVERT(nvarchar, @subscriptionid) 

set @SQLQuery= ';WITH Results_CTE AS ('[email protected] 

    set @SQLQuery= @SQLQuery +') SELECT * FROM Results_CTE WHERE RowNum > '+CONVERT(nvarchar, @skip)+' AND RowNum <= '+CONVERT(nvarchar, @[email protected]) --//paging'; 
END 

EXECUTE sp_executesql @SQLQuery 
Problemi correlati