2010-02-26 17 views
12

Sto costruendo un sistema per l'aggiornamento di grandi quantità di dati tramite vari feed CSV. Normalmente eseguivo il ciclo solo su ciascuna riga del feed, eseguo una query di selezione per verificare se l'elemento esiste già e inserisce/aggiorna un elemento a seconda che esista o meno.Procedure consigliate per l'inserimento/aggiornamento di grandi quantità di dati in SQL Server 2008

Ritengo che questo metodo non sia molto scalabile e che possa martellare il server su feed più grandi. La mia soluzione è quella di scorrere gli elementi normalmente, ma memorizzarli. Quindi, per ogni 100 elementi, effettuare una selezione su questi 100 articoli e ottenere un elenco di elementi esistenti nel database corrispondente. Quindi concatenare insieme le istruzioni di inserimento/aggiornamento ed eseguirle nel database. Questo essenzialmente ridurrebbe i viaggi nel database.

È una soluzione sufficientemente scalabile e ci sono esempi di tutorial sull'importazione di feed di grandi dimensioni in un ambiente produttivo?

Grazie

risposta

13

Vedendo che si sta utilizzando SQL Server 2008, mi sento di raccomandare questo approccio:

  • primo bulkcopy i file CSV in una tabella di gestione temporanea
  • aggiornamento vostra tabella di destinazione da quella tabella di gestione temporanea utilizzando il comando MERGE

Controllare lo MSDN docs e un great blog post su come utilizzare il comando MERGE.

In sostanza, si crea un collegamento tra la tabella di dati reali e la tabella di gestione temporanea su criteri comuni (ad esempio una chiave primaria comune), e quindi è possibile definire che cosa fare quando

  • le righe corrispondono, per esempio la riga esiste sia nella tabella di origine che in quella di destinazione -> in genere si aggiornerebbero alcuni campi o semplicemente si ignorerebbe tutto insieme
  • la riga dalla sorgente non esiste nella destinazione -> in genere un caso per un inserto

Si avrebbe un qualcosa di MERGE dichiarazione come questa:

MERGE TargetTable AS t 
USING SourceTable AS src 
ON t.PrimaryKey = src.PrimaryKey 

WHEN NOT MATCHED THEN 
    INSERT (list OF fields) 
    VALUES (list OF values) 

WHEN MATCHED THEN 
    UPDATE 
    SET (list OF SET statements) 
; 

Naturalmente, la clausola ON può essere molto più coinvolti se necessario. E, naturalmente, le tue istruzioni WHEN possono anche essere più complesse, ad es.

WHEN MATCHED AND (some other condition) THEN ...... 

e così via.

MERGE è un nuovo comando molto potente e molto utile in SQL Server 2008: utilizzalo, se puoi!

2

Un modo è caricare il CSV in un DataTable (o più probabilmente un DataReader) e poi in batch sbattere nei risultati utilizzando SqlBulkCopy -

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

sua piuttosto efficiente e si può fare un po 'di mappatura delle colonne. Suggerimento: quando si mappano le colonne usando SqlBulkCopy sono sensibili al maiuscolo e minuscolo.

0

Un altro approccio sarebbe quello di scrivere un Net stored procedure sul server sul server di operare su tutto il file ...

Solo se avete bisogno di un maggiore controllo rispetto alla soluzione di Kris Krause anche se - Sono un grande fan di mantenerlo semplice (e riusabile) dove possiamo ...

0

Hai bisogno di essere il tuo proprio qui? Sarebbe possibile fornire i dati in modo che SQL Server possa utilizzare l'importazione di massa per caricarlo e quindi gestire i duplicati nel database una volta completata l'importazione?

Quando si tratta di operazioni di sollevamento pesante con molti dati, la mia esperienza tende ad essere che lavorare nel database il più possibile è molto più rapido e meno dispendioso in termini di risorse.

2

Il tuo modo è la peggiore soluzione possibile. In generale, non si dovrebbe pensare in termini di looping attraverso i record individualmente. Avevamo uno strumento di importazione costruito da società che scorreva attraverso i ricordi, ci vorrebbero 18-20 ore per caricare un file con oltre un milione di record (qualcosa che non era frequente quando è stato costruito ma che è molte volte un ora del giorno).

Vedo due opzioni: Inserimento di massa per il primo utilizzo da caricare in una tabella di staging e fare tutto ciò che è necessario fare su quella tabella. Come stai determinando se l'alrady record esiste? Dovresti essere in grado di creare un aggiornamento basato su set unendoti alla tabella di staging su quei campi che determinano l'aggiornamento. Spesso ho aggiunto una colonna alla mia tabella di staging per l'id del record a cui corrisponde e ho popolato che attraverso una query ho fatto l'aggiornamento. Quindi fai un inserto dei record che non ha id corrispondente. Se hai troppi record da fare tutto in una volta, potresti voler eseguire lotti (che sì è un ciclo), ma rendere i batch considerevolmente più grandi di 1 record alla volta (di solito inizio con 2000 e poi in base al tempo necessario per determinare se posso fare più o meno nel lotto).

Penso che il 2008 abbia anche una scheda unione, ma non ho ancora avuto la possibilità di usarlo. Cerca nei libri online.

L'alternativa è utilizzare SSIS ottimizzato per la velocità.SSIS è una cosa complessa però e la curva di apprendimento è ripida.

+0

+1 per l'utilizzo di BULK INSERT & MERGE –

+0

Grazie per il suggerimento. Il motivo per cui faccio il loop di ogni elemento è perché ho bisogno di eseguire alcune convalide e logica di formattazione prima di aggiungerlo al database. Questo poi ritorna all'utente se ci sono problemi con il feed stesso. Mi piace l'idea di unire i dati, però, esaminerò ciò. – markvpc

+0

È possibile eseguire facilmente convalida e formattazione anche in modalità basata su insiemi. Andare a fondo nei singoli record è quasi sempre una scelta sbagliata e non dovresti prendere in considerazione l'idea di farlo finché tutte le altre opzioni non saranno state eliminate. – HLGEM