2010-09-08 6 views
5

Tengo una tabla con 252759 tuplas. Me gustaría usar el objeto DataSet para facilitar mi vida, sin embargo, cuando intento crear un DataSet para mi tabla, después de 3 segundos, obtengo java.lang.OutOfMemory.El conjunto de datos groovy sql provoca java.lang.OutOfMemory

No tengo experiencia con los conjuntos de datos, ¿hay alguna guía sobre cómo usar el objeto DataSet para las tablas grandes?

Respuesta

1

¿Por qué no comenzar con darle a la JVM más memoria?

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

252759 tuplas no suena como algo que un mecanizado con 4 GB de RAM + alguna memoria virtual no podía manejar en la memoria.

+0

¿Es posible hacer datos de recuperación groovy perezosamente? Porque el aumento de la memoria no se escala muy bien. – Skarab

+0

Si desea hacer eso, debe usar JDBC normal. La forma maravillosa en que lo hace, es decir, copiar todo el conjunto de resultados en una lista de arrays, no es adecuado para la recuperación diferida, porque Groovy nunca pudo saber cuándo fue necesario cerrar el conjunto de resultados subyacente, ya que no hay un método explícito close() en la lista ; por lo que debería dejarlo abierto hasta la recolección de basura (lo que podría no suceder pronto), absorbiendo recursos en el servidor de la base de datos. –

+0

Gracias, veo que no entendí la API de DataSet. En mi caso, los registros en la tabla contienen datos textuales y 4GB no es suficiente, por lo tanto, volveré a JDBC. Si tengo tiempo, planeo echar un vistazo también a GORM (Groovy ORM) que es parte de Grails. – Skarab

7

¿Realmente necesita recuperar todas las filas a la vez? De lo contrario, podría recuperarlos en lotes de (por ejemplo) 10000 utilizando el enfoque que se muestra a continuación.

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 es una característica específica de MySQL, pero la mayoría de otros RDBMS tener una característica equivalente que limita el número de filas devueltas por una consulta.

Además, no he probado (ni compilado) el código anterior, ¡así que trátelo con cuidado!

+0

Quería usar DataSet para evitar el uso de raw sql. – Skarab

+0

Si desea tomar este enfoque, debe usar 'Sql'. No parece posible utilizar características de SQL no estándar como 'limit' con' DataSet'. –

+0

@Skarab: por lo general, es una mala idea extraer gran cantidad de datos de su servidor de base de datos para realizar operaciones solo para evitar sql ... Esos datos deben enviarse a través de la red, lo que es mucho más lento que tratar con en el servidor de db. Entonces, de hecho, estás agregando problemas de rendimiento potencialmente paralizantes a tu aplicación haciendo cosas como esas. – NotMe

Cuestiones relacionadas