Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: schumi - Aprile 13, 2012, 03:04:00 pm

Titolo: Importazione CSV su Postgresql
Inserito da: schumi - Aprile 13, 2012, 03:04:00 pm
sto sviluppando un'applicazione utilizzando ZeosLib e PostGresql, ho un problema di lentezza ad importare alcuni CSV, uno di questi conta poco meno di 900.000 righe e ci vogliono alcuni minuti, qualcuno di voi ha esperienza in merito?
grosso modo il codice è così

FDoc := TCSVDocument.Create;
    FDoc.Delimiter := ';';
    FDoc.LoadFromFile(nomefile);
    Tab_tes.Active := True ;
    DecimalSeparator:=','  ;
    DateSeparator := '-' ;
    for t := 0 to FDoc.RowCount - 1 do
    begin
        Tab_tes.Insert ;
        Tab_tes.FieldByName('campo1').AsString := FDoc.Cells[0,t];
        Tab_tes.FieldByName('campo2').AsString := FDoc.Cells[1,t];
        Tab_tes.Post
    end;
   Tab_tes.ApplyUpdates;
   Tab_tes.CommitUpdates ;

Tab_tes è una TZTable

grazie
Titolo: Re:Importazione CSV su Postgresql
Inserito da: nomorelogic - Aprile 13, 2012, 03:21:15 pm
in questi casi io preferisco crearmi uno script senza passare per il dataset

900.000 record in un dataset non sono pochi, sicuramente le ultime insert sono rallentatissime; poi all'ApplyUpdates deve essere generato lo script dai 900.000 inserimenti...

Titolo: Re:Importazione CSV su Postgresql
Inserito da: schumi - Aprile 13, 2012, 04:39:52 pm
quindi leggere il file CSV riga per riga e lanciare un "INSERT INTO" ???
Titolo: Re:Importazione CSV su Postgresql
Inserito da: nomorelogic - Aprile 14, 2012, 09:58:35 am
puoi anche usare TCSVDocument ovviamente, io dicevo di non usare Tab_tes per limitare al massimo il tempo per la composizione della richiesta SQL, ovviamente poi il tempo di esecuzione dello script non cambia

ad esempio potresti provare:

Codice: [Seleziona]
SqlScript := TStringList.Create;
FDoc := TCSVDocument.Create;
try
    FDoc.Delimiter := ';';
    FDoc.LoadFromFile(nomefile);
    DecimalSeparator:=','  ;
    DateSeparator := '-' ;
    for t := 0 to FDoc.RowCount - 1 do
        SqlScript.Add( Format('INSERT INTO TABLENAME (FIELD1, FIELD2) VALUES (''%s'', ''%s'');', [FDoc.Cells[0,t], FDoc.Cells[1,t]]) );
   Tab_tes.SqlConnection.ExecuteDirect(SqlScript.Text); // quì Tab_tes viene usato solo per raggiungere l'istanza della connessione al DB
finally
  SqlScript.Free;
  FDoc.Free;
end;

questa è la sintassi Delphi :P magari qualche metodo cambia nome...
Titolo: Re:Importazione CSV su Postgresql
Inserito da: schumi - Aprile 16, 2012, 08:52:59 am
l'unica modifica che ho dovuto fare al tuo codice è Tab_tes.Connection.ExecuteDirect, effettivamente i tempi diventano più umani.
ho provato anche importando direttamente con il comando di Postgresql COPY nometabella FROM nomefile USING DELIMITERS '';'' CSV, prestazioni ancora migliori però non permette di fare alcun controllo nei dati prima di importarli e ovviamente cambiando DB non funzionerebbe.

Grazie per l'aiuto.