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


27

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 (ove possibile) per questo processo notturno?


Credo che dovresti fornire maggiori dettagli sul tuo tavolo, poiché immagino dipenderebbe dalla potenziale esistenza di indici su campi.
SRKX,

Risposte:


9

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 OPPURE anche se i dati in 5 colonne cambiano e queste 5 colonne sono tutte indicizzate, allora è meglio "eliminare e inserire". Ma se cambiano solo 2 colonne e diciamo che non fanno parte di alcun indice non cluster, allora potresti essere meglio "Aggiornando" i record perché in questo caso verrà aggiornato solo l'indice cluster (e gli indici non dovranno essere aggiornato).


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 è necessario 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 per quelli interni a SQL Server, consultare Kalen Delaney, il libro di Paul Randal e altri - Interni di SQL Server 2008 .


8

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.


1
Non è più veloce di un AGGIORNAMENTO, la stessa meccanica sotto il cofano.
Mark Storey-Smith,

È più veloce dell'aggiornamento e quindi dell'inserimento di quelli che non esistevano già.
datagod

2
Se sai che è così, dimostralo :)
Mark Storey-Smith,

4

Ma io stesso ho controllato Elimina e Inserisci vs Aggiorna su una tabella che ha 30 milioni di record (3 core). 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.


Ho anche affrontato questo caso, ma poi ho scoperto che a volte è possibile ottimizzare una grande fusione aggiungendo indicazioni (temp o perm) alla fonte o alla destinazione, suggerimenti o sottoregolazione della destinazione (non applicabile per l'unione completa).
crokusek,

3

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 è disattivare anche 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.


4
Non sono d'accordo che sia sempre così. Inoltre, la tabella nella domanda di @ adopilot non può essere cancellata da TRUNCATE in quanto contiene record di 89m e vuole aggiornare solo 36k.
Mark Storey-Smith,

bisogno di imparare a leggere il post più attento! aggiornerò il post ... in realtà, devo cambiare molto.
Asken,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.