it-swarm.it

Cosa c'è di meglio per le grandi modifiche a una tabella: ELIMINA e INSERISCI ogni volta o AGGIORNA esistente?

Sto realizzando un progetto in cui devo cambiare circa 36.000 record in una tabella ogni giorno. Mi chiedo cosa funzionerà meglio:

  1. eliminare le righe e inserirne di nuove, oppure
  2. aggiorna le righe già esistenti

Per me è più semplice eliminare tutte le righe e inserirne di nuove, ma se questo frammenterà la tabella, gli indici e l'impatto sulle prestazioni, preferirei fare aggiornamenti ove possibile ed eliminare/inserire solo quando necessario.

Questo sarà un servizio notturno e non sto cercando di migliorare la velocità del processo stesso. Sono più preoccupato per l'esecuzione delle query su questa tabella in generale, dove ho già 89 milioni di dischi e su come questo processo notturno lo influenzerà.

Devo eliminare/inserire record o devo aggiornare quelli esistenti (dove possibile) per questo processo notturno?

27
adopilot

Dipende davvero da quanto dei dati sta cambiando. Supponiamo che questa tabella abbia 20 colonne. E hai anche 5 indici - ognuno su un diff. colonna.

Ora se i valori in tutte e 20 le colonne cambiano OR anche se i dati in 5 colonne cambiano e queste 5 colonne sono tutte indicizzate, allora potresti essere meglio "eliminando e inserendo". cambiano solo 2 colonne e diciamo che non fanno parte di alcun indice non cluster, quindi è meglio "Aggiornare" i record perché in questo caso verrà aggiornato solo l'indice cluster (e gli indici non dovranno essere aggiornati ).


Su ulteriori ricerche, ho scoperto che il mio commento sopra è in qualche modo ridondante poiché SQL Server internamente ha 2 meccanismi separati per eseguire un AGGIORNAMENTO. - Un "aggiornamento sul posto" (ovvero modificando il valore di una colonna con uno nuovo nella riga originale) o come "AGGIORNAMENTO non sul posto" (ELIMINA seguito da un INSERTO).

Gli aggiornamenti sul posto sono la regola e vengono eseguiti se possibile. Qui le righe rimangono esattamente nella stessa posizione sulla stessa pagina nella stessa misura. Solo i byte interessati sono chnaged. Il tlog ha un solo record (a condizione che non vi siano trigger di aggiornamento). Gli aggiornamenti avvengono in caso di aggiornamento di un heap (e lo spazio nella pagina è sufficiente). Gli aggiornamenti si verificano anche se la chiave di clustering cambia ma la riga non deve spostarsi affatto.

Ad esempio: se hai un indice cluster sul cognome e hai i nomi: In grado, Baker, Charlie Ora vuoi aggiornare Baker a Becker. Nessuna riga deve essere spostata. Quindi questo può prendere posto. Considerando che, se devi aggiornare Able a Kumar, le righe dovranno essere spostate (anche se saranno sulla stessa pagina). In questo caso, SQL Server eseguirà un DELETE seguito da un INSERT.

Considerando quanto sopra, suggerirei di eseguire un normale AGGIORNAMENTO e lasciare che SQL Server capisca il modo migliore per farlo internamente.

Per maggiori dettagli sugli interni "AGGIORNAMENTO" o su quelli interni di SQL Server, consultare Kalen Delaney, il libro di Paul Randal e altri - SQL Server 2008 Internals .

10

Hai studiato il comando MERGE in SQL 2008? Ecco un esempio di base:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Questo è fondamentalmente un comando "UPSERT". Aggiorna se esiste, inseriscilo in caso contrario. Comando MOLTO veloce, molto interessante.

8
datagod

Ma io stesso ho controllato Elimina e Inserisci vs Aggiorna su una tabella con 30 milioni di record (3 punti). Questa tabella ha una chiave composita univoca raggruppata e 3 chiavi non cluster. Per Elimina e Inserisci, ci sono voluti 9 minuti. Per l'aggiornamento ci sono voluti 55 minuti. C'è solo una colonna che è stata aggiornata in ogni riga.

Quindi, chiedo a voi persone di non indovinare. Le equazioni cambieranno quando si ha a che fare con tabelle di grandi dimensioni con molte colonne e con molti dati.

4
srinivas

L'aggiornamento non è così veloce. Il trucco è ottenere un inserimento veloce è disabilitare gli indici durante l'inserimento dei dati.

Prendi in considerazione l'utilizzo di questo:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

Ancora più veloce è anche disattivare l'aggiornamento automatico delle statistiche nelle opzioni db. Se la tabella viene modificata in modo significativo, è necessario eseguire:

UPDATE STATISTICS dbo.import_table

o

EXEC sp_updatestats

come lavoro su base regolare (giornaliera, settimanale a seconda della dimensione del db) per mantenere aggiornate le statistiche. La cosa da cercare è aggiornare le statistiche quando la tabella è vuota. Ciò rovinerà le statistiche se non lo esegui dopo che il tavolo è stato popolato di nuovo.

3
Asken