Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 26-03-2015
ronimaxh ronimaxh is offline
Miembro
 
Registrado: jun 2003
Ubicación: Rep. Dominicana
Posts: 307
Poder: 21
ronimaxh Va por buen camino
Question Insercción masiva tarda mucho....

Saludos amigos del club, uso firebird 2.5 y C# estoy haciendo una inserción masiva desde un archivo plano txt que contiene 2.7 millones de registro le inserto 4 campos y tarde 5 horas de la forma que lo hago:

Código:
//leeo el archivo:
  if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string nombre = open.FileName;
                StreamReader Lector = new StreamReader(nombre);
                string Linea = Lector.ReadLine();
                char[] Delimitador = { '|' };
                Int32 CantLineas = File.ReadAllLines(nombre).Length;
                progressBar1.Maximum = CantLineas;
                progressBar1.Minimum = 0;
                progressBar1.Value = 0;
                detener = false;
                CargarRNC carga = new CargarRNC();
               // carga.BorrarCargaRNC();
                int i = 0;
                while (Linea != null)
                {

                    string[] Campos = Linea.Split(Delimitador);
                    carga.Rnc = Campos[0];
                    carga.Cliente = Utilidades.LimpiarCadena(Campos[1]);
                    carga.Usuarioid = 0;
                    carga.FechaSist = Utilidades.ObtenerFechaHoraSist();
                   //llamo un metodo insertar por linea
                    Int32 aff = carga.GuardaCargaRNC(carga);
                    Linea = Lector.ReadLine();
                    progressBar1.Increment(+1);
                    progressBar1.Refresh();
                    i++;
                  
                }
                Lector.Close();
                MessageBox.Show("Preceso Terminado Satisfactoriamente", "Atencion", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
Código:
 //llamo un metodo insertar por linea
 public Int32 GuardaCargaRNC (CargarRNC Carga)
        {
            string sqltxt = "insert into TB_CARGARNC (rnc,cliente,usuarioid,fechasist)values(" + "'" + Carga.Rnc + "'" + "," + "'" + Carga.Cliente + "'" + "," + Convert.ToString(Carga.Usuarioid) + "," + "'" + Carga.FechaSist + "'" + ")";
            FbConnection conn = ConectarFirebirdDB.ObtenerConexion();
            FbTransaction trans = conn.BeginTransaction();
            FbCommand cmd = new FbCommand(sqltxt, conn, trans);
            Int32 aff = 0;
            try
            {
                aff = cmd.ExecuteNonQuery();
                trans.Commit();
               
            }
            catch (Exception ex)
            {
                trans.Rollback();
                
            }
            conn.Close();
            cmd.Dispose();
            return aff;

        }
__________________
ronimaxh
Rep. Dominicana
Responder Con Cita
  #2  
Antiguo 26-03-2015
Avatar de TOPX
TOPX TOPX is offline
Miembro
 
Registrado: may 2008
Ubicación: Bogotá
Posts: 527
Poder: 16
TOPX Va camino a la fama
Saludos,

No conozco el Provider de .Net para FB, pero por favor pruebe el rendimiento del carge:
  • Llamando al Commit solamente después de cierto número de Inserts, por ejemplo cada 1000.
  • Cambiando (alguna propiedad o algún método del FbTransaction) para que la transacción no sea "retaining".
-
__________________
"constructive mind, destructive thoughts"
Responder Con Cita
  #3  
Antiguo 26-03-2015
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.272
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Habría que pasarle un profiler a ese código para ver dónde está tardando. O si no puedes, utilizar algún sistema de debug, para ver qué está tardando cada parte de ese código.

Depende de si tienes triggers y validaciones activadas en la base de Datos.
Hacer un commit cada X registros, como te han comentado, también ayudará.
El realizar refrescos de pantalla (progressbar y similares) también incrementa el tiempo (a veces más de lo que parece). Al igual que los commits, yo suelo hacer estos refrescos cada 1000 o 5000 registros...
Si puedes mantener la conexión abierta, en lugar de abrirla y cerrarla en cada registro, es posible que también ganes tiempo (me ha parecido que lo haces así).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 26-03-2015
ronimaxh ronimaxh is offline
Miembro
 
Registrado: jun 2003
Ubicación: Rep. Dominicana
Posts: 307
Poder: 21
ronimaxh Va por buen camino
gracias por los comentarios, no uso triggers, ni generadores, ni validaciones en la base de Datos, voy a probar lo que me dicen.
__________________
ronimaxh
Rep. Dominicana
Responder Con Cita
  #5  
Antiguo 26-03-2015
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Tienes varios problemas de eficiencia en tu código (aparte que no se ve muy idiomatico), y no estas sacando ventaja de .NET!

La parte importante es que estan cargando (doble) el archivo de texto, en vez de procesar en modo de stream (o linea a linea pa hacerlo mas simplista). Ademas, no estas manejando transacciones ni reusando los planes de ejecucion, ni manejando correctamente los recursos (recursos= handles a BD, archivos, etc... todo lo que es externo a .NET).

Primero, debes anular la idea de hacer el conteo de lineas pa saber el total. Puedes en vez de eso usar el tamaño del archivo en bytes, e ir aumentando los bytes procesados... pero mostrar en porcentaje para que sea menos confuso para el usuario.

Te pongo un ejemplo de como puede quedar (lo tengo con Postgres porque en mi Mac no tengo Firebird):

Código PHP:
using System;
using System.IO;
using Npgsql//Aqui cambia a FB!

namespace test
{
    public 
delegate bool UpdateGui(uint progreso) ;

    class 
MainClass
    
{

        public 
void LoadData(NpgsqlConnection dbstring fileNameUpdateGui ui)
        {
            
//Recorre linea a linea, NO CARGES TODO EL ARCHIVO EN MEMORIA!
            
uint progreso 0;

            foreach (
string line in File.ReadLines(fileName))
            {
                
progreso += 1;
                if (!
ui(progreso)) {
                    break;
                }

                
//Haz la logica de datos aqui...
            
}
                        
        }

        
//Aisla la GUI
        
public bool UpdateGui(uint progreso) {
            
//Ahora esto es mas testeable y puedes aislar el tema de Threading y no
            //bloquear pantalla
            
Console.Write ("Actualizado {0}"progreso);
            return 
true//Informar si se cancela o no
        
}

        public static 
void Main (string[] args)
        {            
            
NpgsqlConnection db = new NpgsqlConnection("CON STRING");

            
//Encapsula acceso a recursos externos (db, filess) con USING!
            //Eso auto-cierra la conexion (como en un TRY/FINALLY
            
using (db) {
                
//Igual encapusla transacciones
                //Procesos en batch = 1 transaccion
                
using (NpgsqlTransaction tran db.BeginTransaction ()) {
                    
//Separa la GUI de la logica
                    
LoadData (db, @"Path archivo"UpdateGui);

                    
tran.Commit ();
                }
            }
        }
    }

Esto es mas idiomatico, y eso que aun se puede hacer mucho mejor con lo que da la nueva funcionalidad de C#/.NET...

Se puede alterar para que haga los commit en batch (ej, cada 100 registros), para lo que debes concatenar los INSERT con un StringBuilder en vez de hacer registro a registro, pero esta es masomenos la idea general...


P.D: Te recomiendo que estudies bien como se hace C# moderno, que te estas perdiendo toda la diversion

En especial busca como hacer:

1- Async/Await
2- yield
3- Un ORM: El mejor es Dapper
4- Que es nuevo en .NET para tu version VS la ultima que recuerdas (ej: Si empezaste con .NET 1, mira que ha ido cambiando hasta la actual) y de ser posible pasate a la ultima version
5- LINQ!

Eso para empezar ;
__________________
El malabarista.

Última edición por mamcx fecha: 26-03-2015 a las 18:25:06.
Responder Con Cita
  #6  
Antiguo 26-03-2015
ronimaxh ronimaxh is offline
Miembro
 
Registrado: jun 2003
Ubicación: Rep. Dominicana
Posts: 307
Poder: 21
ronimaxh Va por buen camino
si te comento que estoy aprendiendo c# soy novato, estoy en el proceso de aprendizaje me a gustado mucho, agradezco cualquier comentario.
__________________
ronimaxh
Rep. Dominicana
Responder Con Cita
  #7  
Antiguo 26-03-2015
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
Cita:
Empezado por mamcx Ver Mensaje
P.D: Te recomiendo que estudies bien como se hace C# moderno, que te estas perdiendo toda la diversion
Creo que también me estoy perdiendo la diversión. Estoy tan acostumbrado a ser altamente productivo en Delphi que nunca he considerado seriamente otro lenguaje para desarrollar aplicaciones de escritorio. En el código que muestra mamcx se nota la potencia y sencillez de c#. Ahora sí, llegó la hora de salir de la zona de confort
Responder Con Cita
  #8  
Antiguo 26-03-2015
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Aunque estoy algo oxidado con Delphi, es posible hacer al dia de hoy algo parecido. Y hay buenas tecnicas de programacion (como aislar la UI) que son universales.

El asunto es que hay que estudiar. Y salir de la "zona de confort" con frequencia: Eso NO OBLIGA a cambiar de lenguaje, mas bien, ayuda a hacer las cosas mejores.

Por ejemplo, en estos dias:

Hice el tutorial de kdb+, leido sobre el lenguaje Elixir & clojure & scala & otros , intentando hacer un lenguaje de programacion en F#...

Y al final siempre termino haciendo todo en python

P.D: Y me parece aun mas instructivo que ver C#, aprender F#:

http://fsharpforfunandprofit.com/

Porque si que te saca de la zona de confort (sin ir TAN lejos como con haskell & clojure)

En especial esto es MUY instructivo:

http://fsharpforfunandprofit.com/fppatterns/
__________________
El malabarista.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Aplicación en Windows 7 64 bits tarda mucho en arrancar jupehe Conexión con bases de datos 2 26-07-2014 10:56:11
Tarda mucho el UPDATE a MySQL b1ast3r Conexión con bases de datos 2 13-10-2010 19:34:56
Tarda mucho en ejecutar un SP Choclito Firebird e Interbase 29 13-08-2010 17:02:46
Form que se tarda mucho en abrir IVAND Varios 3 29-05-2007 02:14:07
Por que tarda mucho en abrir un EXE IcebergDelphi Varios 5 16-06-2004 11:05:28


La franja horaria es GMT +2. Ahora son las 00:57:19.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi