Quoi de mieux pour les grandes modifications apportées à une table: SUPPRIMER et INSÉRER à chaque fois ou METTRE À JOUR existant?

27

Je fais un projet où je dois changer environ 36K enregistrements dans une table quotidiennement. Je me demande ce qui fonctionnera mieux:

  1. supprimer des lignes et en insérer de nouvelles, ou
  2. mettre à jour les lignes déjà existantes

Pour moi, il est plus facile de simplement supprimer toutes les lignes et d'en insérer de nouvelles, mais si cela va fragmenter la table et les index et affecter les performances, je préférerais faire des mises à jour si possible et supprimer / insérer uniquement lorsque cela est nécessaire.

Ce sera un service de nuit et je ne cherche pas à améliorer la vitesse du processus lui-même. Je suis plus préoccupé par les performances des requêtes sur cette table en général où j'ai déjà 89 millions d'enregistrements et comment ce processus nocturne va l'affecter.

Dois-je supprimer / insérer des enregistrements ou dois-je mettre à jour les enregistrements existants (si possible) pour ce processus nocturne?

adopilot
la source
Je pense que vous devriez donner plus de détails sur votre table, car je suppose que cela dépendra de l'existence potentielle d'indices sur les champs.
SRKX

Réponses:

9

Cela dépend vraiment de la quantité de données qui change. Disons que ce tableau comporte 20 colonnes. Et vous avez également 5 index - chacun sur un diff. colonne.

Maintenant, si les valeurs des 20 colonnes changent OU même si les données de 5 colonnes changent et que ces 5 colonnes sont toutes indexées, il vaut mieux "supprimer et insérer". Mais si seulement 2 colonnes changent et permettent de dire que celles-ci ne font partie d'aucun index non clusterisé, alors vous feriez mieux de "mettre à jour" les enregistrements car dans ce cas, seul l'index clusterisé sera mis à jour (et les index n'auront pas à être mis à jour).


Sur des recherches plus poussées, j'ai trouvé que le commentaire ci-dessus par moi est en quelque sorte redondant car SQL Server dispose en interne de 2 mécanismes distincts pour effectuer une MISE À JOUR. - Une "mise à jour sur place" (c'est-à-dire en changeant une valeur de colonne en une nouvelle dans la ligne d'origine) ou comme une "MISE À JOUR non sur place" (SUPPRIMER suivie d'une INSÉRER).

Les mises à jour sur place sont la règle et sont effectuées si possible. Ici, les lignes restent exactement au même emplacement sur la même page dans la même étendue. Seuls les octets concernés sont modifiés. Le tlog n'a qu'un seul enregistrement (à condition qu'il n'y ait pas de déclencheurs de mise à jour). Les mises à jour se produisent sur place si un segment de mémoire est mis à jour (et qu'il y a suffisamment d'espace sur la page). Les mises à jour se produisent également si la clé de clustering change mais que la ligne n'a pas du tout besoin de se déplacer.

Par exemple: si vous avez un index clusterisé sur le nom de famille et que vous avez les noms: Able, Baker, Charlie Maintenant, vous voulez mettre à jour Baker vers Becker. Aucune ligne ne doit être déplacée. Cela peut donc prendre place. Alors que si vous devez mettre à jour Able vers Kumar, les lignes devront être décalées (même si elles seront sur la même page). Dans ce cas, SQL Server effectuera une DELETE suivie d'une INSERT.

Compte tenu de ce qui précède, je vous suggère de faire une MISE À JOUR normale et de laisser SQL Server trouver la meilleure façon de le faire en interne.

Pour plus de détails sur les internes «MISE À JOUR» ou d'ailleurs sur les internes liés à SQL Server, consultez le livre de Kalen Delaney, Paul Randal et al. - SQL Server 2008 Internals .

Dharmendar Kumar «DK»
la source
8

Avez-vous étudié la commande MERGE dans SQL 2008? Voici un exemple de 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) ;

Il s'agit essentiellement d'une commande "UPSERT". Mettez à jour s'il existe, insérez-le si ce n'est pas le cas. Commande TRÈS rapide, très cool.

datagod
la source
1
Ce n'est pas plus rapide qu'une MISE À JOUR, même mécanique sous le capot.
Mark Storey-Smith,
C'est plus rapide que de mettre à jour puis d'insérer ceux qui n'existaient pas déjà.
datagod
2
Si vous savez que c'est le cas, prouvez-le :)
Mark Storey-Smith
4

Mais, j'ai moi-même vérifié la suppression et l'insertion par rapport à la mise à jour sur une table qui a 30 millions d'enregistrements (3 crores). Cette table a une clé composite unique en cluster et 3 clés non cluster. Pour Supprimer et insérer, cela a pris 9 minutes. Pour la mise à jour, il a fallu 55 minutes. Il n'y a qu'une seule colonne qui a été mise à jour dans chaque ligne.

Donc, je vous demande de ne pas deviner. Les équations changeront lorsqu'il s'agit d'un grand tableau avec de nombreuses colonnes et beaucoup de données.

srinivas
la source
J'ai également rencontré ce cas, mais j'ai découvert qu'il était parfois possible d'optimiser une fusion importante en ajoutant des indices (temp ou perm) à la source ou à la cible, des conseils ou en sous-définissant la cible (ne s'applique pas à la fusion complète).
crokusek
3

La mise à jour n'est pas aussi rapide. L'astuce consiste à réaliser une insertion rapide consiste à désactiver les index pendant l'insertion des données.

Pensez à utiliser ceci:

-- 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

Il est encore plus rapide de désactiver également la mise à jour automatique des statistiques dans les options de la base de données. Si la table est considérablement modifiée, vous devez exécuter:

UPDATE STATISTICS dbo.import_table

ou

EXEC sp_updatestats

comme un travail sur une base régulière (quotidienne, hebdomadaire selon la taille de la base de données) pour maintenir les statistiques à jour. La chose à surveiller est de mettre à jour les statistiques lorsque la table est vide. Cela va bousiller les statistiques si vous ne l'exécutez pas après que la table a été remplie à nouveau.

Asken
la source
4
Je ne pense pas que ce soit toujours le cas. De plus, le tableau de la question de @ adopilot ne peut pas être effacé par TRUNCATE car il contient 89m d'enregistrements et il ne souhaite mettre à jour que 36k.
Mark Storey-Smith,
besoin d'apprendre à lire le post plus attentivement! je vais mettre à jour le message ... en fait, je dois beaucoup changer.
Demande