Foros del Web » Programación para mayores de 30 ;) » Java »

Cómo optimizar la importación de datos desde un archivo plano a BD PostgreSQL ?

Estas en el tema de Cómo optimizar la importación de datos desde un archivo plano a BD PostgreSQL ? en el foro de Java en Foros del Web. Buenos días a la comunidad, tengo una consulta le sucede que tiene que importar 14 millones de registros que contienen la información de los clientes ...
  #1 (permalink)  
Antiguo 14/05/2014, 10:55
Avatar de Sumerio  
Fecha de Ingreso: octubre-2009
Mensajes: 195
Antigüedad: 15 años, 1 mes
Puntos: 6
Pregunta Cómo optimizar la importación de datos desde un archivo plano a BD PostgreSQL ?

Buenos días a la comunidad, tengo una consulta le sucede que tiene que importar 14 millones de registros que contienen la información de los clientes de una empresa.
Archivos planos. Txt pesa 2,8 GB, he desarrollado un programa de Java que lee el fichero línea a línea plana, tratar la información y ponerla en un objeto que a su vez se inserta en una tabla en la base de datos PostgreSQL, el tema es que he hecho un cálculo que 100.000 registros insertados en un tiempo de 112 minutos, pero el problema es que tengo que insertar los registros por partes.

Código:
public static void main(String[] args) {  

  // PROCESAMIENTO 100,000 registros en 112 minutos 
  // PROCESAMIENTO 1,000,000 registros en 770 minutos = 18,66 horas

  loadData(0L, 0L, 100000L);
}

/ ** 
  * Carga el número de registros en función de los parámetros de entrada. 
  * @ Param counterInitial - Contador inicial, tipo long. 
  * @ Param loadInitial - Carga inicial, tipo long. 
  * @ Param loadLimit - Límite de carga, tipo long. 
  * /
private static void loadData(long counterInitial, long loadInitial, long loadLimit){
  Session session = HibernateUtil.getSessionFactory().openSession(); 
  try{
      FileInputStream fstream = new FileInputStream("C:\\sppadron.txt");
      DataInputStream entrada = new DataInputStream(fstream);
      BufferedReader buffer = new BufferedReader(new InputStreamReader(entrada));
      String strLinea;
      while ((strLinea = buffer.readLine()) != null){
          if(counterInitial > loadInitial){
              if(counterInitial > loadLimit){
                  break;
              }
              Sppadron spadron= new Sppadron();
              spadron.setSpId(counterInitial);                
              spadron.setSpNle(strLinea.substring(0, 9).trim());
              spadron.setSpLib(strLinea.substring(9, 16).trim());
              spadron.setSpDep(strLinea.substring(16, 19).trim());
              spadron.setSpPrv(strLinea.substring(19, 22).trim());
              spadron.setSpDst(strLinea.substring(22, 25).trim());
              spadron.setSpApp(strLinea.substring(25, 66).trim());
              spadron.setSpApm(strLinea.substring(66, 107).trim());
              spadron.setSpNom(strLinea.substring(107, 143).trim());                   
              String cadenaGriSecDoc = strLinea.substring(143, strLinea.length()).trim();                    
              String[] tokensVal = cadenaGriSecDoc.split("\\s+");
              if(tokensVal.length == 5){
               spadron.setSpNac(tokensVal[0]);
               spadron.setSpSex(tokensVal[1]);
               spadron.setSpGri(tokensVal[2]);
                  spadron.setSpSec(tokensVal[3]);
                  spadron.setSpDoc(tokensVal[4]);
              }else{
               spadron.setSpNac(tokensVal[0]);
               spadron.setSpSex(tokensVal[1]);
               spadron.setSpGri(tokensVal[2]);
                  spadron.setSpSec(null);
                  spadron.setSpDoc(tokensVal[3]);
              }
              try{
                  session.getTransaction().begin();
                  session.save(spadron); // Insert
                  session.getTransaction().commit(); 
              } catch (Exception e) {
                  session.getTransaction().rollback();
                  e.printStackTrace();
              }
          }
          counterInitial++;
      }
      entrada.close();  
  } catch (Exception e) {
      e.printStackTrace();
  }finally{
      session.close();
  }
}
El problema principal es si comprueban mi código cuando inserto el primer millón de registros,
los parámetros serían los siguientes:
Código:
loadData (0L, 0L, 1000000L);
El tema es que al insertar los siguientes registros en este caso sería el siguiente millón de registros serían:
Código:
loadData (0L, 1000000L, 2000000L);
Qué va a hacer que desplazarse por el millon registros, hasta que cuando el contador llegue al valor de 1,000,001
y luego recien comenzará ha insertar los siguientes registros.
Alguien me puede dar una sugerencia más óptima para insertar los registros, sabiendo que es necesario tratar información,
como se ve en el código anterior que muestro.
  #2 (permalink)  
Antiguo 14/05/2014, 11:12
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 20 años, 1 mes
Puntos: 454
Respuesta: Cómo optimizar la importación de datos desde un archivo plano a BD Postgre

¿Por qué lo haces por bloques?

Abre el fichero una sola vez, lee línea a línea e inserta cada línea.

Si quieres más eficiencia, no uses hibernate, usa directamente JDBC con PreparedStatement y Batch para inserciones http://chuwiki.chuidiang.org/index.p...Insert_en_Java

Otra forma eficiente (más posiblemente) es usar el comando sql copy de postgresql http://www.postgresql.org/docs/curre.../sql-copy.html que es capaz de leer e insertar un fichero que tenga un formato concreto. Quizás puedas hacer que tu programa java lea el fichero y lo convierta al formato que necesita postgresql para luego usar este comando copy.

Si tienes que hacerlo por bloques como muestras en el código y las líneas son de longitud fija, puedes usar la clase RandomAccessFile, que te permite abrir el fichero en un byte concreto, sin necesidad de leer todo secuencialmente.

Si las líneas no son de la misma longitud y tienes que hacerlo por bloques, no tienes opciones, salvo que sepas seguro que te van a llamar a loadData() consecutivamente, de forma que entre llamada y llamada podrías guardarte en qué byte del fichero estás y usar entonces RandomAccessFile para la siguiente llamada yendo directamente a ese byte.

Se bueno.
__________________
Apuntes Java
Wiki de Programación

Etiquetas: bd, objeto, plano, postgresql, programa, string, valor
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:41.