Ottenere le file inserite con SqlBulkCopy

linq-to-sql sqlbulkcopy sql-server transactions

Domanda

Sto passando alcuni dei miei Linq al codice Sql per usare SqlBulkCopy, e il problema è che ho bisogno di fare due inserti di più migliaia di righe in due tabelle.

Il servizio prende il tuo lotto di 10.000 link (importati da sitemap, builder backlink, ecc.) E li taglia in feed RSS di X per feed per l'aggregazione. Il problema è che ho già una tabella di 32 milioni di righe . Se faccio inserimenti da linq a sql, esso richiede in base al traffico del sito tra 5 e 10 minuti per caricare 10.000 link.

La struttura è molto semplice.

Feed : Id bigint (PK), Title varchar (1000), Descrizione varchar (1000), Data pubblicazione, Aggregated datetime null, ShortCode varchar (8) [antiquato, non più inserito, ma utilizzato per dati legacy]

Articoli : Id bigint (PK), FeedId bigint (FK), Titolo varchar (1000), Descrizione varchar (1000), Data pubblicazione, ShortCode varchar (8) [antiquato, non più inserito, ma utilizzato per dati legacy], ShortId bigint null [aggiornato dopo l'inserimento con uguale Id (utilizzato nel partizionamento)]

FutureItems : Id bigint (PK), FeedId bigint (FK), Titolo varchar (1000), Descrizione varchar (1000), Pubblicato datetime, ShortCode varchar (8) [antiquato, non inserito più, ma usato per dati legacy], ShortId bigint null [aggiornato dopo l'inserimento con uguale Id (utilizzato nel partizionamento)]

OldItems : Id bigint (PK), FeedId bigint (FK), Titolo varchar (1000), Descrizione varchar (1000), Data pubblicazione, ShortCode varchar (8) [antiquato, non inserito più, ma utilizzato per dati legacy], ShortId bigint null [aggiornato dopo l'inserimento con uguale Id (utilizzato nel partizionamento)]

Quindi se hai una dimensione del feed di 20, ottieni 500 inserti nella tabella Feeds, quindi 10000 inseriti nella tabella Items, quindi aggiorna le esecuzioni per impostare ShortId uguale all'Id. Una volta a notte, viene eseguito un lavoro che separa i dati nelle altre due tabelle e sposta gli articoli futuri nella tabella Articoli.

Ho letto che SqlBulkCopy può fare 20 milioni di righe in materia di mintues, ma non riesco a trovare alcun buon esempio di farlo in più tabelle con un vincolo FK.

Il nostro server SQL è un "mostro" in particolare per questa applicazione. È SQL 2008 R2 Web, Windows 2008 R2 Enterprise, 12 GB Ram, Dual 4 core Xeons @ 2.8ghz.

Il nostro server web è un clone senza il servizio di database.

Quando si inseriscono i collegamenti, la CPU esegue circa l'85% e il database riempie la RAM.

Se SqlBulkCopy non è buono, qualsiasi suggerimento è ben accetto, abbiamo clienti paganti che si stanno arrabbiando e io non sono un DBA, solo un semplice programmatore.

Risposta accettata

SqlBulkCopy è infatti più veloce degli inserti ordinari. Ma è più veloce in quanto può trasformare un lavoro che esegue 1000 inserti al secondo in uno che fa 10000 / sec. Se è possibile eseguire solo 10000 collegamenti in 10 minuti, è necessario che si verifichino problemi diversi, il che è improbabile che la copia di massa venga risolta.

È necessario prima capire perché ci vuole così tanto tempo per inserire 10000 link. Solo dopo aver capito, puoi effettuare una chiamata che determina se passare a SqlBulkCopy è una soluzione. Comprendo che non sei un DBA, ma ti indicherò un white paper "scadente" per la risoluzione dei problemi relativi alle prestazioni di SQL Server: Waits and Queues . Questa non è una soluzione per la ricetta di un cookie cutter, è in realtà una metodologia che ti insegnerà come identificare i colli di bottiglia delle prestazioni in SQL Server.

E per rispondere alla tua domanda: come si usa SqlBulkCopy quando ci sono dei vincoli? La domanda più generica è: come si fa un'operazione di inserimento di massa quando sono presenti dei vincoli? Per i volumi gravi, in realtà si disabilitano i vincoli, si eseguono i caricamenti collettivi, quindi si ripristinano i vincoli. Per operazioni online più snelle con tempi di inattività minimi (il database è fondamentalmente 'inattivo' per il periodo in cui i vincoli sono disabilitati) si usa una strategia diversa, vale a dire precarica i dati nelle tabelle di staging, lo convalida e quindi lo inoltra con un funzionamento dell'interruttore di partizione, vedere Trasferimento efficiente dei dati mediante il cambio di partizione .


Risposta popolare

Penso che il tuo vero problema nell'usare un semplice inserto di massa sia che hai bisogno degli ID dei feed dall'inserto iniziale per le altre tabelle. Ecco cosa farei. Utilizza l'inserimento collettivo da inserire in una tabella di staging. Quindi utilizzare un proc memorizzato per eseguire gli inserimenti nella tabella reale in modalità basata su insiemi. Puoi utilizzare la clausola di output nell'inserzione iniziale nella tabella feed per recuperare una variabile di tabella con gli ID feed necessari per gli inserimenti nelle altre tabelle.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché