2013-01-16 17 views
14

Desidero poter recuperare tutti i record da una tabella molto grande utilizzando Slick. Se provo a farlo attraverso foreach, for o list fetching; Ottengo un'eccezione di memoria insufficiente.Scala Slick Lazy Fetch

C'è un modo per utilizzare "cursori" con caricamento Slick o pigro che recupera l'oggetto solo quando necessario riducendo la quantità di memoria utilizzata?

+0

Non sono sicuro del motivo per cui foreach risulterebbe in una OOM, dovrebbe procedere solo un elemento alla volta. Puoi invece provare elementi(), che restituiranno un CloseableIterator. Se questo risulta anche in una OOM, inserisci il resto del codice. – Saish

+1

Qualche aggiornamento su questo? – S0rin

risposta

6

Non so che cosa si intende per cursori, ma è possibile recuperare i dati parziali utilizzando impaginazione:

query.drop(0).take(1000) will take the first 1000 records 

query.drop(1000).take(1000) will take from 1001 to 2000 lines of the table. 

Ma questa efficienza query dipenderà dalla vostra base di dati, se lo sosterrà, se la tabella è giusto indicizzato.

+1

Sì, ho pensato che, il fatto è che volevo qualcosa come un 'fetchNext' solo per afferrare il prossimo record nel set di risultati. Sembra che il 'foreach' preleva tutti i risultati in una lista (esaurimento della memoria nel processo). Forse posso implementare la mia funzione per recuperare parte del set di risultati utilizzando la tecnica di impaginazione. GRAZIE –

+0

Perché non utilizzare la chiazza di petrolio [iteratore] (http://slick.typesafe.com/doc/1.0.1/api/index.html#scala.slick.util.CloseableIterator)? – matanster

+0

@matt In passato, l'iteratore di posizionamento posizionato causava un errore di memoria, ma penso che questo problema sia stato risolto. Iterator ha anche i metodi Take & Drop, ma penso che intendi usare i metodi next e hasnext, giusto? – dirceusemighini

1

è possibile utilizzare la combinazione di iterator che restituisce un iteratore:

val object = Objects.where(...).map(w => w).iterator() 

e un groupby:

val chunkSize = 1000 
val groupedObjects = objects.grouped(chunkSize) 
groupedObjects.foreach {objects => objects.par.map(h => doJob(h))} 

come suggerire a rispondere a questa answer

+0

hai perso una s alla fine della definizione degli oggetti val – dirceusemighini

0

di dirceusemighini è corretto. Mi sono imbattuto in un problema simile pochi giorni fa a causa di errato presupposto su Query.list(), quindi posso dare qualche altro contesto. Da Slick reference:

"Le query vengono eseguite utilizzando i metodi definiti nel tratto Invoker (o UnitInvoker per le versioni senza parametri) .C'è una conversione implicita da Query, quindi è possibile eseguire qualsiasi query direttamente. leggendo un risultato completo impostato in una raccolta rigorosa con un metodo specializzato come elenco o il metodo generico a cui è possibile creare qualsiasi tipo di raccolta "

È vero che Query.list() carica il set di risultati completo in memoria . Con questo in mente, puoi avere più approcci per il tuo problema.

Problemi correlati