Acceso a la Base de Datos

Hola, estoy realizando una aplicacion web en donde me conecto a una base de datos (Oracle), todo funciona correctamente con datos pequeños, pero cuando realizo insert's por arriba de los 100 000 silmutaneamente, el rendimiento del sistema baja drasticamente ( 19 minutos para 100 000 inserts). Queria saber si alguien puede ayudarme con alguna clase ejemplo usando algun metodo para solucionar esto. Me conecto usando JDBC, gracias de antemano.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Java, o la base de datos?

Creo que primero tienes que identificar si el problema está en tu código Java o en la base de datos. De entrada te recomiendo utilizar una transacción si te es posible: obten tu conexión, quitale el autocommit, inicia una transaccion, haz tus 100mil inserts, dale commit. A ver si eso te ayuda.
Supongo que tus 100mil inserts los haces con la misma conexión... si no, empieza por usar una misma conexión para hacer los 100mil inserts. Si eso no te es posible por alguna razón, entonces utiliza un pool de conexiones a la base de datos, algo como el Commons DBCP de Jakarta. Configuras un DataSource que hace un pool de conexiones y dichas conexiones se van a mantener abiertas; cuando le pides a dicho DataSource una conexión nueva, lo que hace es realmente tomar una de las que tiene libres. Cuando cierras la conexión, se devuelve al pool. Esto es mucho más eficiente que estar creando y cerrando conexiones físicas a la base de datos.
Si usas alguna otra cosa para hacer 100mil inserts (un script de bash por ejemplo) se tarda lo mismo? Eso te va a indicar si el problema está en Oracle o en tu programa. Tal vez la tabla tiene demasiados índices y por eso se tarda, pero aún así se me hace demasiado 19 minutos para 100mil inserts). Intenta quitarle los índices a la tabla, hacer los inserts y luego ponerle los índices nuevamente; si el tiempo se reduce drásticamente, entonces ya encontraste tu problema y tendrás que solucionarlo por fuera de Java.
El tiempo que se tarda en los inserts es lineal? Es decir, si haces 10mil inserts se tarda 2 minutos, o se tarda mucho menos y el tiempo va creciendo de manera exponencial (de modo que 200mil inserts en vez de 38 minutos se podrían tardar digamos 3 horas)? Si el tiempo crece de manera exponencial entonces es más probable que el problema esté en tu código Java.
Por el momento es lo que se me ocurre; si pones más información (número de campos, número de registros existentes en la tabla, hardware specs del servidor Oracle, etc) eso ayudaría a encontrar el problema.

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time. - Steve Riley

Imagen de iberck

Podrías poner el código

Podrías poner el código del insert ?
Tal vez estas utilizando String en lugar de StringBuilder/StringBuffer

Hola

Este es el metodo que mando a llamar en un ciclo for

/**
* Inserta en la tabla INSUMO el insumo que le fue pasado como parametro
* @param insumo Bean Insumo
*/
public void setEntradaInsumo(Insumo insumo, Connection conexion) throws java.sql.SQLException
{

query = conexion.prepareStatement("INSERT INTO INSUMO (IDINSUMO, IDTIPOHOLOGRAMA, FOLIO_INSUMO, TIPO_ASIGNACION, FECHA_ADQUISICION) "+
"VALUES (seq_insumo.nextval,?,?,?,?)");

query.setInt(1, insumo.getIdTipoHolograma());
query.setInt(2, insumo.getFolioInsumo());
query.setInt(3, insumo.getTipoAsignacion());
query.setString(4, insumo.getFechaAdquisicion());

query.executeUpdate();

query.close();
}

Lo hago con una sola conexion y al terminar el ciclo cierro la conexion. Utilizo JDBC para conectarme con Oracle

Imagen de iberck

ok, y el for ?

ok, y el for ?

FOR

Sale, te pongo todo el doPost:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
objConexion = new Conexion();
conexion = objConexion.getConexion();

try
{
folioInicial = Integer.valueOf(request.getParameter("txtFolioInicial"));
folioFinal = Integer.valueOf(request.getParameter("txtFolioFinal"));
fechaEntrada = request.getParameter("txtFechaEntrada");
tipoHolograma = Integer.valueOf(request.getParameter("cmbTipoHolograma"));

//tiempoInicial = System.currentTimeMillis();
for(int i = folioInicial; i<=folioFinal; i++)
{
Insumo insumo = new Insumo();

insumo.setFechaAdquisicion(fechaEntrada);
insumo.setIdTipoHolograma(tipoHolograma);
insumo.setFolioInsumo(i);
insumo.setTipoAsignacion(0);

metodos.setEntradaInsumo(insumo,conexion);
}
//tiempoFinal = System.currentTimeMillis() - tiempoInicial;
}
catch(java.lang.NumberFormatException e)
{
mensaje = "Error! \\n\\n Los datos insertados son incorrectos, favor de verificar su informacion.";
}
catch(java.sql.SQLException e2)
{
mensaje = "Error! \\n\\n Los folios ya se encuentra registrados, favor de vericar sus datos.";
}
catch(Exception e3)
{
mensaje = "Error! \\n\\n Se genero un error al intentar guardar el o los registros.";
}
}

Imagen de iberck

Para empezar, el código del

Para empezar, el código del servlet no es thread safe a menos que lo tengas configurado como singlethread mode (No recomendable)
Crea variables locales para q se guarden en el stack de cada thread

JavaRanch Big Moose Saloon member.

Imagen de ezamudio

varios statements?

Segun yo, no es necesario que hagas un nuevo PreparedStatement para cada insert. Justamente la idea de un PreparedStatement es que ya lo tengas y lo puedas reusar. Asi que lo creas afuera del ciclo, una sola vez, y dentro del ciclo le pones parametros para cada nueva tupla y lo ejecutas (no lo cierras; de hecho creo que para un INSERT no es necesario el close, ese metodo es mas bien para queries que devuelven ResultSets).
Revisa la documentación, yo ahorita no tengo tiempo pero si mal no recuerdo esa es precisamente la idea de los PreparedStatements.

Por otro lado, estas creando una nueva instancia de Insumo en cada iteración, que solamente estás usando para encapsular 4 valores. Mejor refactoriza tu método para que reciba los 4 valores directamente. O en todo caso, crea un solo Insumo afuera del ciclo, y le vas poniendo los valores dentro del ciclo y pasándolo (no veo que hagas otra cosa con ese objeto mas que ponerle valores, pasarlo al método que inserta, y ahí dentro leer dichos valores).

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time. - Steve Riley