J'ai une instance SQL Server 2008 avec environ 150 colonnes. J'ai déjà rempli ce tableau avec environ 12 millions d'entrées, mais j'ai depuis effacé le tableau en préparation d'un nouvel ensemble de données.
Cependant, les commandes qui fonctionnaient autrefois instantanément sur une table vide, comme count(*)
et select top 1000
dans, SQL Management Studio
prennent maintenant des éons pour s'exécuter.
SELECT COUNT(*) FROM TABLE_NAME
a pris plus de 11 minutes pour renvoyer 0 et SELECT TOP 1000
a mis près de 10 minutes pour renvoyer une table vide.
J'ai également remarqué que l'espace libre sur mon disque dur a littéralement disparu (de 100 à 20 G environ). La seule chose qui s'est produite entre les deux est une seule requête que j'ai exécutée:
DELETE FROM TABLE_NAME
Que se passe-t-il dans le monde?!?
TRUNCATE TABLE
place deDELETE FROM
.Réponses:
On vous a déjà expliqué pourquoi
TRUNCATE
serait tellement plus rapide / meilleur / plus sexy queDELETE
, mais il reste une question à résoudre:Pourquoi est
SELECT
plus lent après avoirDELETE
terminé ?En effet,
DELETE
a seulement fantôme les lignes. Le tableau est tout aussi grand que lorsqu'il avait 12 millions de lignes, même s'il n'en a pas. Pour compter les lignes (0), il faut autant de temps qu'il a fallu pour compter 12 millions de lignes. Avec le temps, le processus de nettoyage des fantômes va ramasser ces enregistrements fantômes et désallouer les pages qui ne contenaient que des fantômes, et vos SELECT accéléreront. Mais en ce moment, si vous vous enregistrez,Skipped Ghosted Records/sec
perfmon monte probablement en flèche pendantSELECT COUNT(*)
. Vous pouvez également accélérer les choses par la reconstruction de la table:ALTER TABLE ... REBUILD
.TRUNCATE
aurait également pris soin de ce problème, car il ne laisse aucun fantôme derrière.Voir également À l'intérieur du moteur de stockage: nettoyage en profondeur de Ghost .
la source
DELETE
Les instructions suppriment des lignes d'une table une par une, en enregistrant chaque ligne dans latransaction log
, ainsi qu'en conservant leslog sequence number (LSN)
informations. Puisque vous avez mentionné que votre table contenait d'énormes données (12 millions d'enregistrements), après la suppression de laquelle votre disque dur est à court d'espace, vérifiez la taille de votre fichier journal de base de données. Il aurait très probablement grandi.Une meilleure façon aurait été:
la source
(C'était à l'origine un commentaire à la réponse de @ DaveE, mais je l'ai mis dans sa propre réponse car elle est longue)
TRUNCATE
est une opération enregistrée. Il doit en être autrement, il n'est pas conforme à ACID. Cependant, les différences entreTRUNCATE
etDELETE
:TRUNCATE
journalisation : enregistre uniquement les pages / extensions * libérées, tandis queDELETE
les lignes individuelles sont enregistrées.TRUNCATE
verrous : utilise généralement moins de verrous, car il faut un verrou de table et des verrous de page, par opposition à celuiDELETE
qui utilise des verrous de ligne **.IDENTITY
séquences:TRUNCATE
réinitialise la séquence d'identité sur une table, si elle est présente.(* Une extension = 8 pages.
TRUNCATE
Enregistrera / supprimera les extensions si elles sont toutes de cette même table, sinon elle enregistrera / supprimera les pages des extensions mixtes.** Un effet secondaire de cela est que
DELETE FROM TABLE
des pages vides peuvent potentiellement être allouées à la table, selon que l'opération peut obtenir un verrou de table exclusif ou non.)Donc (retour à la question d'origine),
TRUNCATE TABLE
c'est nettement mieux queDELETE FROM TABLE
si vous videz la table mais que vous souhaitez conserver la structure (NB:TRUNCATE
ne peut pas être utilisé sur une table référencée par une clé étrangère d'une autre table).Comme indiqué dans le commentaire de @ Tullo, vérifiez également le modèle de récupération de votre base de données - s'il est plein, vous devez soit commencer à prendre des sauvegardes de journaux, soit changer votre modèle de récupération en simple. Une fois que vous avez effectué l'une de ces opérations, vous souhaiterez probablement réduire votre fichier journal en tant qu'opération unique (NB: fichier journal uniquement ) afin de récupérer tout cet espace libre.
Enfin, une autre chose à savoir - les statistiques de table. exécutez
UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE` pour que l'optimiseur de requêtes ne soit pas gâché par les anciennes statistiques.la source
(REMARQUE: je ne suis pas un DBA) DELETE est une opération enregistrée et ne libère pas l'espace utilisé. Vous disposez probablement d'un grand journal des transactions occupant de l'espace et des analyses de table s'exécutant sur l'espace table «vide». Je suppose que vous devez effacer le journal des transactions et réduire votre base de données. Cet article StackOverflow devrait vous aider à démarrer.
Et utilisez TRUNCATE TABLE lorsque vous souhaitez le faire à l'avenir.
EDIT: Ma déclaration sur TRUNCATE non connecté était en erreur. supprimé.
la source