Script SQL per update o insert

venerdì 27 maggio 2011 - 11.06
Tag Elenco Tags  SQL Server 2005

jenga Profilo | Newbie

Leggendo un altro thread mi è venuto questo dubbio: ho diverse procedure di caricamento di datawarehouse su tabelle molto "popolose", e ogni giorno devo trasferire qualche centinaio di migliaia di record.

Solitamente la procedura controlla se il record esiste (sulla chiave), e se esiste lo aggiorna, altrimenti lo inserisce.

La maggior parte delle procedure esistono da tempo e sono scritte in questo modo (ipotizzando che id sia la chiave della tabella), con un cursore che ripete queste operazioni record per record:
Update Table SET col=..., col2=..., col3=... WHERE id=@id if @@rowcount = 0 INSERT INTO Table VALUES @col, @col2, @col3

Cercando qua e la per ottimizzare i tempi, ho trovato la stessa cosa fatta in modo diverso:
IF EXISTS (SELECT * FROM Table WHERE id=@id) BEGIN UPDATE Table SET col=....,col2....c,ol3=.... WHERE id=@id END ELSE BEGIN INSERT INTO Table (cols here) VALUES (here) END
così a occhio non saprei dire quale è più performante, e prima di mettermi a fare test e stravolgere come sono scritte le procedure attuali, vorrei un vostro parere...

Avevo anche pensato di utilizzare SSIS per questo tipo di operazioni, visto che i cursori in T-SQL sono veramente lenti.
Però fare un aggiornamento di questo tipo (update o insert) con SSIS ho visto che è piuttosto elaborato.
(per esempio ho visto questo: http://consultingblogs.emc.com/jamiethomson/archive/2006/09/12/SSIS_3A00_-Checking-if-a-row-exists-and-if-it-does_2C00_-has-it-changed.aspx)
L'alternativa che avevo in mente è utilizzare i componenti lookup:
verifico se un record esiste nella tabella di destinazione; se c'è lo cancello.
faccio la insert di tutti i record (nuovi e "vecchi")

non mi piace molto nemmeno così...
si accettano suggerimenti!
grazie


--
Igor Brusetti
http://jenga.wordpress.com

alx_81 Profilo | Guru

>Solitamente la procedura controlla se il record esiste (sulla
>chiave), e se esiste lo aggiorna, altrimenti lo inserisce.
>La maggior parte delle procedure esistono da tempo e sono scritte
>in questo modo (ipotizzando che id sia la chiave della tabella),
>con un cursore che ripete queste operazioni record per record:
>così a occhio non saprei dire quale è più performante, e prima
>di mettermi a fare test e stravolgere come sono scritte le procedure
>attuali, vorrei un vostro parere...
se avessi almeno 2008, potresti usare la merge, così puoi passare tabelle ed evitare i cursori..
http://technet.microsoft.com/en-us/library/bb510625.aspx

ma leggo 2005, quindi l'idea del cursore, in ogni caso non mi piace per niente.
Prova a pensare di caricare in insert only un livello di staging intermedio, con le stesse chiavi della tabella di destinazione.
Poi con due soli statement, fai l'update dei record con la stessa chiave e l'insert da una from (left o right join) che esclude i record che combaciano.

>Avevo anche pensato di utilizzare SSIS per questo tipo di operazioni,
>visto che i cursori in T-SQL sono veramente lenti.
>Però fare un aggiornamento di questo tipo (update o insert) con
>SSIS ho visto che è piuttosto elaborato.
>L'alternativa che avevo in mente è utilizzare i componenti lookup:
>verifico se un record esiste nella tabella di destinazione; se
>c'è lo cancello.
molto pesante con molti record, ma meglio dei cursori cmq.

>faccio la insert di tutti i record (nuovi e "vecchi")
anche in questo caso sto scrivendo un post per la gestione degli inserimenti incrementali.
Se usi SSIS in combinazione con quanto detto prima, secondo me trovi la soluzione vincente.
Inoltre puoi pensare anche a partizionare le tabelle per sfruttare gli algoritmi di switch.

>si accettano suggerimenti!
>grazie
di nulla!

--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

jenga Profilo | Newbie

>>faccio la insert di tutti i record (nuovi e "vecchi")
>anche in questo caso sto scrivendo un post per la gestione degli
>inserimenti incrementali.
>Se usi SSIS in combinazione con quanto detto prima, secondo me
>trovi la soluzione vincente.
>Inoltre puoi pensare anche a partizionare le tabelle per sfruttare
>gli algoritmi di switch.

credo che mi indirizzerò sulla strada del SSIS, mi sembra anche più manutenibile, nonostante la maggiore complessità nel realizzarlo.
partizionare tabelle? mmm devo leggermi il BOL su questo argomento.
--
Igor Brusetti
http://jenga.wordpress.com

alx_81 Profilo | Guru

>credo che mi indirizzerò sulla strada del SSIS, mi sembra anche
>più manutenibile, nonostante la maggiore complessità nel realizzarlo.
>partizionare tabelle? mmm devo leggermi il BOL su questo argomento.
parti da qui http://technet.microsoft.com/en-us/library/dd578580(SQL.100).aspx

anche in caso di utilizzo di ssis, cerca di creare una tabella speculare alla destinazione così da fare insert dei record che non combaciano (per chiave) e update di quelli che combaciano. Operando set based le prestazioni aumenteranno molto.
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5