Pour exécuter une requête SQL prend beaucoup de time

J'ai deux tables. Les arrays 2 contiennent des loggings plus récents. Le tableau 1 contient 900 000 loggings et le tableau 2 à peu près la même chose.

Pour exécuter la requête ci-dessous prend environ 10 minutes. La plupart des requêtes (au moment de l'exécution de la requête ci-dessous) à la table 1 donnent une exception de timeout d'expiration.

DELETE T1 FROM Table1 T1 WITH(NOLOCK) LEFT OUTER JOIN Table2 T2 ON T1.ID = T2.ID WHERE T2.ID IS NULL AND T1.ID IS NOT NULL 

Quelqu'un pourrait-il m'aider à optimiser la requête ci-dessus ou à écrire quelque chose de plus efficace? Aussi comment réparer le problème avec le problème de time mort?

L'optimiseur choisira probablement de bloquer toute la table car il est plus facile de le faire s'il doit supprimer autant de lignes. Dans ce cas, je supprime en morceaux.

 while(1 = 1) begin with cte as ( select * from Table1 where Id not in (select Id from Table2) ) delete top(1000) cte if @@rowcount = 0 break waitfor delay '00:00:01' -- give it some rest :) end 

La requête supprime donc 1000 lignes à la fois. L'optimiseur verrouillera probablement juste une page pour supprimer les rangées, pas la table entière.

Le time total d'exécution de cette requête sera plus long, mais il ne bloquera pas les autres appelants.

Disclaimer: supposé MS SQL.

Une autre approche consiste à utiliser la transaction SNAPSHOT . De cette façon, les lecteurs de table ne seront pas bloqués pendant la suppression des lignes.

Attendez une seconde, essayez-vous de faire ça …

 DELETE Table1 WHERE ID NOT IN (SELECT ID FROM Table2) 

?

Si oui, c'est comme ça que je l'écrirais. Vous pouvez également essayer de mettre à jour les statistics sur les deux tables. Et bien sûr, les index sur Table1.ID et Table2.ID pourraient accélérer considérablement les choses.

EDIT: Si vous obtenez des timeouts d'expiration du concepteur, augmentez la valeur du timeout d'attente "Designer" dans SSMS (la valeur par défaut est 30 secondes). devises -> Options -> Concepteurs -> "Remplacer la valeur de timeout de la string de connection pour les mises à jour du concepteur de table" -> entrer un nombre raisonnable (en secondes).

Les deux colonnes d'ID ont besoin d' un index

Ensuite, utilisez un SQL plus simple

 DELETE Table1 WHERE NOT EXISTS (SELECT * FROM Table2 WHERE Table1.ID = Table2.ID)