J'ai des déclarations comme celle-ci qui arrivent à expiration:
DELETE FROM [table] WHERE [COL] IN ( '1', '2', '6', '12', '24', '7', '3', '5')
J'ai essayé de faire un à la fois comme ça:
DELETE FROM [table] WHERE [COL] IN ( '1' )
et jusqu'à présent, il est à 22 minutes et continue.
Le tableau contient 260 000 lignes et quatre colonnes.
Quelqu'un at-il une idée de la raison pour laquelle cela serait si lent et comment l'accélérer? J'ai un index non unique, non-cluster sur le [COL] sur lequel je fais le WHERE. J'utilise SQL Server 2008 R2
mise à jour: je n'ai aucun déclencheur sur la table.
Ce qui peut ralentir une suppression:
Vous devez donc déterminer ce qui bloque et le réparer ou exécuter les suppressions en dehors des heures où ils ne gêneront pas la charge de production normale. Vous pouvez exécuter la suppression par lots (utile si vous avez des déclencheurs, une suppression en cascade ou un grand nombre d'enregistrements). Vous pouvez supprimer et recréer les index (mieux si vous pouvez le faire aussi en dehors des heures de travail).
Désactiver CONSTRAINT
ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;
Désactiver l'index
ALTER INDEX ALL ON [TableName] DISABLE;
Reconstruire l'index
ALTER INDEX ALL ON [TableName] REBUILD;
Activer CONTRAINT
ALTER TABLE [TableName] CHECK CONSTRAINT ALL;
Supprimer à nouveau
La suppression de nombreuses lignes peut être très lente. Essayez de supprimer quelques-uns à la fois, comme:
delete top (10) YourTable where col in ('1','2','3','4')
while @@rowcount > 0
begin
delete top (10) YourTable where col in ('1','2','3','4')
end
Action préventive
Vérifiez à l'aide de SQL Profiler
pour la cause première de ce problème. Il se peut que Triggers
soit à l'origine du retard d'exécution. Cela peut être n'importe quoi. N'oubliez pas de sélectionner le Database Name
et Object Name
lors du démarrage de Trace
pour exclure l'analyse des requêtes inutiles ...
Filtrage des noms de bases de données
Filtrage de noms de tables de procédures stockées/déclencheurs
Action corrective
Comme vous l'avez dit, votre table contient 260 000 enregistrements ... et IN Predicate
contient six valeurs. Maintenant, chaque enregistrement est recherché 260 000 fois pour chaque valeur dans IN Predicate
. Au lieu de cela, il devrait s'agir de la jointure interne, comme ci-dessous ...
Delete K From YourTable1 K
Inner Join YourTable2 T on T.id = K.id
Insérer le IN Predicate
valeurs dans un Temporary Table
ou Local Variable
Si la table que vous supprimez a des déclencheurs BEFORE/APRES EFFACER, il se peut que quelque chose s'y trouvant puisse provoquer votre retard.
De plus, si vous avez des clés étrangères référençant cette table, des UPDATE ou DELETE supplémentaires peuvent se produire.
Il est possible que d'autres tables aient une contrainte FK pour votre [table]. La base de données doit donc vérifier ces tables pour maintenir l'intégrité référentielle. Même si vous avez tous les index nécessaires correspondant à ces FK, vérifiez leur montant.
J'ai eu la situation quand NHibernate créé incorrectement FK dupliqué s sur les mêmes colonnes, mais avec des noms différents (ce qui est autorisé par SQL Server). Il a considérablement ralenti l'exécution de l'instruction DELETE.
Dans mon cas, les statistiques de la base de données avaient été corrompues. La déclaration
delete from tablename where col1 = 'v1'
prenait 30 secondes même s’il n’y avait pas d’enregistrement correspondant mais
delete from tablename where col1 = 'rubbish'
a couru instantanément
fonctionnement
update statistics tablename
corrigé le problème
Si vous supprimez tous les enregistrements de la table plutôt que quelques-uns, il peut être beaucoup plus rapide de simplement supprimer et recréer la table.
[COL] est-il vraiment un champ de caractères contenant des chiffres ou pouvez-vous vous débarrasser des guillemets simples autour des valeurs? @Alex a raison, IN est plus lent que =, donc si vous pouvez le faire, vous serez mieux loti:
DELETE FROM [table] WHERE [COL] = '1'
Mais il vaut mieux utiliser des nombres plutôt que des chaînes pour trouver les lignes (SQL aime les nombres):
DELETE FROM [table] WHERE [COL] = 1
Peut-être essayer:
DELETE FROM [table] WHERE CAST([COL] AS INT) = 1
Dans les deux cas, assurez-vous de disposer d'un index sur la colonne [COL] pour accélérer l'analyse de la table.
J'ai lu cet article, c'était vraiment utile pour résoudre tout type d'inconvénient
https://support.Microsoft.com/en-us/kb/22445
c'est un cas de waitresource KEY: 16: 72057595075231744 (ab74b4daaf17)
-- First SQL Provider to find the SPID (Session ID)
-- Second Identify problem, check Status, Open_tran, Lastwaittype, waittype, and waittime
-- iMPORTANT Waitresource select * from sys.sysprocesses where spid = 57
select * from sys.databases where database_id=16
-- with Waitresource check this to obtain object id
select * from sys.partitions where hobt_id=72057595075231744
select * from sys.objects where object_id=2105058535
Vérifiez le plan d'exécution de cette instruction de suppression. Jetez un coup d'oeil si index chercher est utilisé. Aussi, quel est le type de données de col?
Si vous utilisez un type de données incorrect, changez l'instruction update (comme de '1' à 1 ou N'1 ').
Si l'analyse d'index est utilisée, envisagez d'utiliser indice de requête ..
Après avoir inspecté un package SSIS (en raison de l’exécution très lente de commandes par SQL Server), configuré dans un de nos clients environ 5 ou 4 ans avant le moment où j’écrivais cela, j’ai découvert qu’il existait les tâches ci-dessous: 1 ) insérez les données d’un fichier XML dans une table appelée [Importbarcdes].
2) commande de fusion sur une autre table cible, en utilisant comme source la table susmentionnée.
3) "supprimer de [Importbarcodes]", pour effacer le tableau de la ligne insérée après la lecture du fichier XML par la tâche du package SSIS.
Après une inspection rapide, toutes les instructions (SELECT, UPDATE, DELETE, etc.) de la table ImportBarcodes, qui ne comportait qu'une seule ligne, prenaient environ 2 minutes.
Les événements étendus ont affiché beaucoup de notifications d’attente PAGEIOLATCH_EX.
Aucun index de la table n'était présent et aucun déclencheur n'a été enregistré.
Lors de l’examen approfondi des propriétés de la table, dans l’onglet Stockage et dans la section générale, le champ Espace de données affichait plus de 6 GIGABYTES d’espace alloué en pages.
Qu'est-il arrivé:
La requête a fonctionné pendant une bonne partie de la journée chaque jour au cours des 4 dernières années, insérant et supprimant des données dans la table, laissant les fichiers d'échange inutilisés sur place sans les libérer.
C'est donc la raison principale des événements d'attente capturés par la session d'événements étendus et des commandes exécutées lentement sur la table.
Fonctionnement ALTER TABLE ImportBarcodes REBUILD
résolu le problème libérant tout l'espace inutilisé. TRUNCATE TABLE ImportBarcodes
a fait la même chose, avec la seule différence de supprimer tous les fichiers de page et toutes les données.