2010-09-08 8 views
5

Mam tabelę z 252759 krotkami. Chciałbym użyć obiektu DataSet, aby moje życie było łatwiejsze, jednak gdy próbuję utworzyć DataSet dla mojego stołu, po 3 sekundach otrzymuję java.lang.OutOfMemory.Groovy sql dataset powoduje, że java.lang.OutOfMemory

mam żadnego doświadczenia z zbiorów danych, czy są jakieś wytyczne, jak używać obiektu DataSet dla dużych tabel?

Odpowiedz

1

Dlaczego nie zacząć od udzielenia JVM większej ilości pamięci?

java -Xms<initial heap size> -Xmx<maximum heap size> 

252759 krotki nie brzmi jak coś się maching z 4GB RAM + pewnym pamięci wirtualnej nie mogła poradzić sobie w pamięci.

+0

Czy można leniwie wyszukiwać groovy? Ponieważ zwiększenie pamięci nie skaluje się zbyt dobrze. – Skarab

+0

Jeśli chcesz to zrobić, musisz użyć normalnego JDBC. Sposób, w jaki robi to groovy, tj. Skopiowanie całego zestawu wyników do listy tablic, nie jest odpowiedni do leniwego pobierania, ponieważ Groovy nigdy nie wie, kiedy jest zapisywany, aby zamknąć podstawowy zestaw wyników, ponieważ nie ma wyraźnej metody close() na liście ; więc musiałby pozostawić to otwarte do czasu wyrzucenia śmieci (co może nie nastąpić w najbliższym czasie), zasysając zasoby na serwer bazy danych. –

+0

Dziękuję, widzę, że nie rozumiem interfejsu DataSet API. W moim przypadku zapisy w tabeli zawierają dane tekstowe, a 4 GB to za mało, więc wrócę do JDBC. Jeśli mam czas, planuję przyjrzeć się również GORM (Groovy ORM), który jest częścią Grails. – Skarab

7

Czy na pewno potrzebujesz pobrać wszystkie wiersze naraz? Jeśli nie, możesz po prostu pobrać je partiami (na przykład) 10000 za pomocą podejścia pokazanego poniżej.

def db = [url:'jdbc:hsqldb:mem:testDB', user:'sa', password:'', driver:'org.hsqldb.jdbcDriver'] 

def sql = Sql.newInstance(db.url, db.user, db.password, db.driver) 
String query = "SELECT * FROM my_table WHERE id > ? ORDER BY id limit 10000" 

Integer maxId = 0 

// Closure that executes the query and returns true if some rows were processed 
Closure executeQuery = { 

    def oldMaxId = maxId 
    sql.eachRow(query, [maxId]) { row -> 

     // Code to process each row goes here..... 
     maxId = row.id 
    } 
    return maxId != oldMaxId 
} 


while (executeQuery()); 

AFAIK limit jest MySQL określonej funkcji, ale większość innych RDBMS mają równoważną funkcję, która ogranicza liczbę wierszy zwróconych przez zapytanie.

Również nie testowałem (lub nawet skompilowany) kod powyżej, więc poradzić się ostrożnie!

+0

Chciałem użyć DataSet, aby uniknąć używania surowego sql. – Skarab

+0

Jeśli chcesz zastosować to podejście, musisz użyć 'Sql'. Nie wydaje się możliwe używanie niestandardowych funkcji SQL, takich jak 'limit' z' DataSet'. –

+0

@Skarab: Zazwyczaj nie jest dobrym pomysłem wyciąganie dużej ilości danych z serwera bazy danych w celu wykonywania operacji tylko po to, aby uniknąć sql ... Te dane muszą być przesyłane przez sieć, która jest znacznie wolniejsza niż po prostu do czynienia z na serwerze db. W efekcie dodajesz potencjalnie paraliżujące problemy z wydajnością do swojej aplikacji, wykonując takie czynności. – NotMe

Powiązane problemy