2010-03-26 11 views
9

Sto lavorando con un database mysql piuttosto grande (diverse milioni di righe) con una colonna che memorizza le immagini BLOB. L'applicazione tenta di catturare un sottoinsieme delle immagini e su di esse esegue alcuni algoritmi di elaborazione. Il problema che sto incontrando è che, a causa del set di dati piuttosto grande che ho, il set di dati restituito dalla mia query è troppo grande per essere archiviato in memoria.Gestione di un enorme set di risultati SQL

Per il momento, ho modificato la query per non restituire le immagini. Durante l'iterazione sul set di risultati, eseguo un'altra selezione che cattura l'immagine individuale correlata al record corrente. Funziona, ma le decine di migliaia di query aggiuntive hanno comportato una riduzione delle prestazioni inaccettabile.

La mia prossima idea è di limitare la query originale a 10.000 risultati o così, e quindi continuare a interrogare su spanne di 10.000 righe. Questo sembra compromettere il mezzo della strada tra i due approcci. Sento che probabilmente c'è una soluzione migliore di cui non sono a conoscenza. C'è un altro modo per avere solo porzioni di un gigantesco set di risultati in memoria alla volta?

Cheers,

Dave McClelland

+0

Forse i problemi di memoria non sono causati dalla query. Sono tornato a una versione precedente (grazie, controllo della versione), e il datareader sembra caricare solo la riga che sta leggendo, come citato da Anthony. Ancora, mi chiedo se non abbia più senso conservare le immagini sul filesystem locale invece di trasferirle sulla rete dal server DB (come menzionato da ProphetBeal sotto). Lo svantaggio è che sarebbe memorizzato in entrambe le posizioni (devono rimanere nel DB per l'uso di altri sistemi), ma lo spazio di archiviazione del filesystem non è un problema immediato. Qualche idea su questo? –

+0

Sto dando la risposta ad Anthony perché ha sottolineato che il DataReader non è il motivo per cui la mia memoria si stava riempiendo (era qualcosa di correlato, ma leggermente diverso). Probabilmente userò la soluzione di ProphetBeal per mantenere i BLOB sul computer locale per eliminare la congestione della rete, ma per chiunque abbia a che fare con un set di dati di grandi dimensioni da archiviare sul computer locale, un DataReader dovrebbe essere una soluzione efficace. –

risposta

3

Un'opzione consiste nell'utilizzare un DataReader. Trasmette i dati, ma è a scapito di mantenere una connessione aperta al database. Se stai ripetendo più di un milione di righe ed esegui l'elaborazione per ciascuna di esse, ciò potrebbe non essere desiderabile.

Penso che stai andando verso il basso nel modo giusto di afferrare i dati in blocchi, probabilmente usando il metodo Limite di MySql, corretto?

+0

Sì, avevo programmato di usare il limite di SQL. –

+0

Inoltre, sto già utilizzando un DataReader per archiviare i risultati (utilizzando OdbcCommand.ExecuteReader(), quindi con iterazione while (datareader.Read()). Sembra non eseguire lo streaming in modo molto efficace poiché riempiva ancora tutta la memoria di sistema disponibile C'è un uso di datareader di cui non sono a conoscenza? –

+0

@Dave, qualcun altro potrebbe essere in grado di offrire informazioni sull'uso specifico della memoria del datareader, ma la mia comprensione è che dovrebbe avere un solo record in memoria In ogni caso, dovrebbe richiedere molto meno risorse di memoria di un DataSet o DataTable. I tuoi problemi di memoria potrebbero essere il risultato di ciò che stai facendo con i dati una volta che li hai recuperati, per quanto tempo sei mantenere tali oggetti in ambito, ecc. –

1

Quando si tratta di questi grandi serie di dati è importante non avere bisogno di avere tutto in memoria in una sola volta. Se stai scrivendo il risultato su disco o su una pagina web, fallo come indicato in ogni riga. Non aspettare di aver letto tutte le righe prima di iniziare a scrivere.

È anche possibile impostare le immagini su DelayLoad = true in modo che vengano recuperate solo quando sono necessarie anziché implementare questa funzionalità autonomamente. Vedi here per maggiori informazioni.

+0

Avrei dovuto accennare, sto usando (attualmente) ADO.NET. Esiste un equivalente a DelayLoad? Potrei migrare a Linq, ma preferirei non farlo. Aggiornerò i tag delle domande Inoltre, non sto scrivendo i risultati da nessuna parte. Sto eseguendo alcuni algoritmi di analisi delle immagini sui risultati per confrontarli con un'immagine passata nella funzione. Di conseguenza, ho solo bisogno di memorizzare l'immagine migliore e posso ignorare il resto. Grazie per la rapida risposta! –

0

Vedo 2 opzioni.

1) se si tratta di un'app di Windows (al contrario di un'app Web) è possibile leggere ciascuna immagine utilizzando un lettore di dati e scaricare il file in una cartella temporanea sul disco, quindi è possibile eseguire qualsiasi elaborazione necessaria per contro il file fisico.

2) Leggere e elaborare i dati in piccoli blocchi. Le 10 righe possono ancora essere molto diverse a seconda della dimensione delle immagini e della quantità di processi che si desidera eseguire. Restituire 5k di righe alla volta e leggere di più in un thread separato quando si scende a 1k rimanenti da elaborare può rendere un processo continuo.

Anche se non sempre consigliato, forzare la garbage collection prima di elaborare il prossimo set di righe può aiutare a liberare memoria.

0

ho usato una soluzione come quella descritta in questo tutorial prima: http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/data-access/tutorial-25-cs.aspx

Si potrebbe utilizzare il multi-threading di controllare la validità tirare una parte dei prossimi set di dati (in un primo momento tirare 1-10,000 e in lo sfondo tira 10,001 - 20,000 e 20,001-30,000 righe e cancella le pagine precedenti dei dati (diciamo se sei da 50.000 a 60.000 elimina le prime 1-10.000 righe per risparmiare memoria se questo è un problema). posizione della "pagina" corrente come puntatore per tirare il prossimo intervallo di dati o eliminare alcuni dati fuori range.

Problemi correlati