2012-09-13 13 views
6

Ho bisogno di migliorare le prestazioni del caricamento dei dati. L'algoritmo corrente fa un pieno di selezione da una tabella:Come migliorare le prestazioni di inserimento/aggiornamento dei dati?

select Field1, Field2,...,FieldN from Table1 order by FieldM 

I nuovi dati vengono letti da un file di testo (ad esempio, la linea file di testo per riga DataTable). La tabella ha una chiave primaria, contenente due campi. Per ogni riga di un file di testo individua la riga necessaria da questi due campi (ad esempio la chiave primaria).

query.Locate('Field1;Field2',VarArrayOf([Value1,Value2]),[]); 

If Locate rendimenti True, edita la riga, altrimenti si aggiunge uno nuovo.

Quindi, per quanto riguarda la tabella composta da circa 200000 righe, ciascuna operazione Locate richiede un certo periodo di tempo ... quindi riesce ad aggiornare circa 5-6 righe al secondo.

Quali cose dovrei considerare per migliorarlo?

Probabilmente sostituire l'individuazione tramite questa grande selezione con query separate?

risposta

10

NON utilizzare Locate(). Se si utilizza locate(), Delphi cerca la riga sul lato client solo eseguendo la scansione del set di righe dalla query richiede molto tempo.

Se si dispone di accesso a MSSQL per creare stored procedure, quindi creare la seguente procedura e solo eseguirlo per ogni riga dal file TEXT senza alcuna condizione (utilizzare TAdoStoredProc.ExecProc in Delphi). Quindi in questo caso non è necessario prima selezionare e individuare la procedura. Aggiorna se Archiviato1 e Campo2 vengono trovati e inseriti se non lo fanno.

CREATE PROCEDURE dbo.update_table1 
@Field1 int, --key1 
@Field2 int, --key2 
@Field3 int, -- data fileds 
@Field4 int 

AS 

SET NOCOUNT ON 
update table1 set [email protected],[email protected] 
     where [email protected] and [email protected]; 
IF(@@Rowcount=0) 
BEGIN 
    insert into table1(Field1,Field2,Field3,Field4) 
       values (@Field1,@Field2,@Field3,@Field4); 
END 
GO 

Ecco il codice Delphi per richiamare questa stored procedure con ADO:

...... 
var 
    ADOStoredP: TADOStoredProc; 

    ...... 
begin 

........ 
    ADOStoredP:=TADOStoredProc.Create(nil); 
    try 
     ADOStoredP.Connection:=DataMod.SQL_ADOConnection; //Your ADO Connection instance here 
     ADOStoredP.ProcedureName:='Update_table1'; 
     ADOStoredP.Parameters.CreateParameter('@Field1', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field2', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field3', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field4', ftInteger, pdInput, 0, 0); 

     While() -- Your text file loop here 
     begin 

     ADOStoredP.Parameters.ParamByName('@Field1').Value:=Field1 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field2').Value:=Field2 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field3').Value:=Field3 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field4').Value:=Field4 value from text file here; 

     ADOStoredP.ExecProc; 

     end 

    finally 
     if Assigned(ADOStoredP) then 
     begin 
     ADOStoredP.Free; 
     end; 
    end; 

........ 
end; 
+3

Questa soluzione ha ridotto il tempo di caricamento da 4 ore a meno di 4 minuti. Apprezzo molto il vostro aiuto! Grazie! – horgh

5
  1. Se è possibile, è necessario inviare il file di testo al server che esegue SQL Server. Quindi utilizzare OPENROWSET(BULK) per aprire il file di testo (consultare "E. Utilizzo del provider di OPENROWSET BULK con un file di formato per recuperare le righe da un file di testo").
  2. Se non è possibile inviare il file di testo al server, quindi creare una tabella DB temporanea o persistente e utilizzare INSERT per inserire tutte le righe di file di testo nella tabella.
  3. Se si utilizza SQL Server 2008, è necessario utilizzare l'operatore MERGE. Se è più vecchia versione di SQL Server, è possibile utilizzare due comandi SQL: UPDATE e INSERT. E come sorgente dati usa (1) OPENROWSET o (2) tabella DB.
+0

Anche se era molto più facile da applicare la risposta Valex alla mia situazione, grazie per l'aiuto. Il server sql di destinazione è addirittura il 2000. Uno piuttosto vecchio. Rifare l'algoritmo per caricare i file in una tabella temporanea (e così via ...) non vale alcun guadagno in termini di prestazioni (se esiste) rispetto a quello che ho ottenuto (e quanto tempo ho speso per farlo) grazie all'idea data da valex . Comunque grazie! – horgh