J'ai une grande table de données. Il y a 10 millions d'enregistrements dans ce tableau.
Quel est le meilleur moyen pour cette requête
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
sql-server
sql-server-2008
sql-optimization
user3107343
la source
la source
Réponses:
Si vous supprimez toutes les lignes de cette table, l'option la plus simple consiste à tronquer la table, quelque chose comme
Tronquer la table videra simplement la table, vous ne pouvez pas utiliser la clause WHERE pour limiter les lignes supprimées et aucun déclencheur ne sera déclenché.
D'autre part, si vous supprimez plus de 80 à 90% des données, par exemple, si vous avez un total de 11 millions de lignes et que vous souhaitez supprimer 10 millions, une autre façon serait d'insérer ces 1 million de lignes (enregistrements que vous souhaitez conserver ) vers une autre table intermédiaire. Tronquez ce grand tableau et réinsérez ces 1 million de lignes.
Ou si les autorisations / vues ou d'autres objets qui ont cette grande table comme table sous-jacente ne sont pas affectés par la suppression de cette table, vous pouvez obtenir cette quantité relativement petite de lignes dans une autre table, supprimer cette table et créer une autre table avec le même schéma et les importer rangées dans cette table ex-Large.
Une dernière option à laquelle je peux penser est de changer votre base de données,
Recovery Mode to SIMPLE
puis de supprimer les lignes par lots plus petits en utilisant une boucle while quelque chose comme ça.et n'oubliez pas de changer le mode de récupération à plein et je pense que vous devez faire une sauvegarde pour le rendre pleinement affectif (les modes de changement ou de récupération).
la source
optimal solution for unknown case
c'est le rêve n'est-ce pas? Malheureusement, vous ne pouvez pas guérir toutes les maladies avec une seule pilule; J'ai suggéré des solutions possibles pour différents scénarios. Il n'y a malheureusement pas de balle en argent ici.La réponse @ m-ali est correcte, mais gardez également à l'esprit que les journaux peuvent augmenter beaucoup si vous ne validez pas la transaction après chaque segment et effectuez un point de contrôle. Voici comment je le ferais et prendrais cet article http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes comme référence, avec des tests de performances et des graphiques:
la source
COMMIT TRANSACTION
etCHECKPOINT
les grumes continuent de croître. Merci d'avoir précisé cela.@Deleted_Rows
à 10000 ou vous pourriez vous retrouver avec une boucle infinie en raison de la suppression indéfinie de petits ensembles de données. DoncWHILE (@Deleted_Rows = 10000)
- dès qu'il n'y a pas une "page" complète de données à supprimer, elle s'arrête. Dans votre implémentation,WHILE (@Deleted_Rows > 0)
la boucle while s'exécutera à nouveau même si elle n'a supprimé qu'une seule ligne, et la prochaine exécution pourrait également trouver une ligne ou deux à supprimer - résultant en une boucle infinie.WHILE
boucle elle - même:dateadd(MONTH,-7,GETDATE())
.WHILE
boucle.Vous pouvez également utiliser GO + combien de fois vous souhaitez exécuter la même requête.
la source
GO xx
censée fonctionner? J'obtiens une erreur "Impossible de trouver la procédure stockée ''" . Sans laGO
commande, cela fonctionne bien.@Francisco Goldenstein, juste une petite correction. Le COMMIT doit être utilisé après avoir défini la variable, sinon le WHILE sera exécuté une seule fois:
la source
Cette variante de M.Ali fonctionne très bien pour moi. Il en supprime certains, efface le journal et se répète. Je regarde le journal grandir, tomber et recommencer.
la source
# of rows
pour supprimer à la fois, ainsi que laWHERE
clause. Fonctionne comme un charme!Si vous êtes disposé (et capable) à implémenter le partitionnement, c'est une technique efficace pour supprimer de grandes quantités de données avec peu de temps d'exécution. Pas rentable pour un exercice ponctuel, cependant.
la source
J'ai pu supprimer 19 millions de lignes de mon tableau de 21 millions de lignes en quelques minutes . Voici mon approche.
Si vous avez une clé primaire auto-incrémentée sur cette table, vous pouvez utiliser cette clé primaire.
Obtenez la valeur minimale de la clé primaire de la grande table où readTime <dateadd (MONTH, -7, GETDATE ()). (Ajoutez un index sur readTime, s'il n'est pas déjà présent, cet index sera de toute façon supprimé avec la table de l'étape 3.). Permet de le stocker dans une variable 'min_primary'
Insérez toutes les lignes ayant la clé primaire> min_primary dans une table intermédiaire (table mémoire si le nombre de lignes n'est pas grand).
Déposez la grande table.
Recréez la table. Copiez toutes les lignes de la table intermédiaire vers la table principale.
Supprimez la table intermédiaire.
la source
Vous pouvez supprimer de petits lots en utilisant une boucle while, quelque chose comme ceci:
la source
Une autre utilisation:
Optionnel;
Si le journal des transactions est activé, désactivez les journaux des transactions.
la source
Syntaxe plus courte
la source
Si vous utilisez SQL Server 2016 ou version ultérieure et si votre table comporte des partitions créées en fonction de la colonne que vous essayez de supprimer (par exemple, colonne d'horodatage), vous pouvez utiliser cette nouvelle commande pour supprimer des données par partitions.
TABLE TRONCÉE AVEC (PARTITIONS ({|} [, ... n]))
Cela supprimera les données de la ou des partitions sélectionnées uniquement et devrait être le moyen le plus efficace de supprimer des données d'une partie de la table car cela ne créera pas de journaux de transactions et sera effectué aussi rapidement que la troncature normale, mais sans supprimer toutes les données. de la table.
L'inconvénient est que si votre table n'est pas configurée avec une partition, vous devez alors aller à l'ancienne et supprimer les données avec une approche régulière, puis recréer la table avec des partitions afin que vous puissiez le faire à l'avenir, ce que j'ai fait. J'ai ajouté la création et la suppression de partition dans la procédure d'insertion elle-même. J'avais une table avec 500 millions de lignes, donc c'était la seule option pour réduire le temps de suppression.
Pour plus de détails, reportez-vous aux liens ci-dessous: https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017
SQL Server 2016 Tronquer la table avec des partitions
Voici ce que j'ai fait en premier pour supprimer les données avant de pouvoir recréer la table avec des partitions contenant les données requises. Cette requête s'exécutera pendant des jours pendant la fenêtre de temps spécifiée jusqu'à ce que les données soient supprimées.
la source
Si je dis sans boucle, je peux utiliser une
GOTO
instruction pour supprimer une grande quantité d'enregistrements à l'aide du serveur SQL. exa.de cette façon, vous pouvez supprimer une grande quantité de données avec une taille de suppression plus petite.
laissez-moi savoir si vous avez besoin de plus d'informations.
la source