Optimisation d'une requête de mise à jour pour un grand set de données dans SQL Server 2008

J'ai une requête (voir ci-dessous) dans un triggersur de mise à jour d'une table et mettre à jour certains champs sur un grand set de données sur la base de ce qui est actuellement mis à jour dans le sortinggger.Pour un set de 100000 loggings, il prend environ 22 sec. optimiser cela plus

update RED set EDR_IsLock = @il where RED.docid in (select a.DocID from (select distinct DocID from UVD where UVD.UVID in (select i.UVID from inserted i)) a left outer join (select distinct UVD.DocID from UVD inner join UVH on UVD.UVID = UVH.UVID where UVD.UVID not in (select i.UVID from inserted i) and UVH.IsLock = 1) b on a.DocID = b.DocID where b.DocID is null) 

PS: La Table Rouge contient plus d'un sortingllion d'loggings

Je réécrirais personnellement ceci comme:

 UPDATE RED SET EDR_IsLock = @il WHERE RED.DocID IN ( SELECT UVD.DocID FROM UVD WHERE RED.DocID = UVD.DocID AND NOT EXISTS (SELECT 1 FROM inserted i WHERE i.UVID = UVD.UVID) AND NOT EXISTS ( SELECT UVD.DocID FROM UVD AS UVD2 WHERE UVD2.DocID = UVD.DocID AND EXISTS (SELECT 1 FROM UVH WHERE UVH.UVID = UVD2.UVID AND UVH.IsLock = 1) AND NOT EXISTS (SELECT 1 FROM inserted i WHERE i.UVID = UVD2.UVID) ) ); 

Dans tous les cas, je remplace JOIN , et IN avec EXISTS . SQL Server a un problème avec l'utilisation de LEFT JOIN/IS NULL pour supprimer des loggings, comme documenté ici , dans le meilleur des cas, vous obtiendrez des performances égales à NOT EXISTS , mais parfois LEFT JOIN sera pire. LEFT JOIN/IS NULL n'est pas capable d'utiliser une anti-jointure (arrête la search / parsing dès qu'un logging est trouvé) de la même manière que EXISTS Avec votre méthode actuelle, vous select tous les loggings de UVD correspondent aux critères, vous les sortingez ensuite pour que les duplicates puissent être supprimés, puis utilisez ces résultats pour supprimer les loggings trouvés dans la sous-requête a .

Une logique similaire s'applique à INNER JOIN , en remplaçant par EXISTS vous dites à SQL Server que vous ne vous souciez pas de ce que l'logging est dans UVH , vous vous souciez juste qu'il y en a un.

Le seul autre changement que j'ai réellement fait est de changer NOT IN en NOT EXISTS , cela pourrait potentiellement ne rien faire, mais NOT IN provoquera un comportement inattendu si des loggings NULL sont présents.

Avec ces modifications effectuées, vous devez ensuite exécuter la requête et afficher le plan d'exécution réel. Cela aidera à identifier les goulots d'étranglement, et SQL Server peut même suggérer des index qui accéléreraient la requête.

Essayez Join au lieu de dans la clause. Essayez ci-dessous, cela pourrait vous aider.

 Update r Set EDR_IsLock = @il From RED As r Join ( Select a.DocID From ( Select Distinct DocID From UVD Join inserted i On UVD.UVID = i.UVID ) a left outer join ( Select Distinct UVD.DocID From UVD join UVH on UVD.UVID = UVH.UVID Where UVD.UVID Not In (Select i.UVID From inserted i) And UVH.IsLock = 1 ) b on a.DocID = b.DocID Where b.DocID is null ) As t On r.docid = t.DocID 

Mettre à jour:

Je ne suis pas un bon explicateur, mais si "Non Existe" fait une différence de signification au lieu de "En Clause", alors je réécrirais la requête ci-dessus comme suit:

 Set Nocount On; Declare @UVD Table ( DocID Int ) Declare @UVDWithUVH Table ( DocID Int ) Insert Into @UVD(DocID) Select Distinct DocID From UVD As u With (Nolock) Join inserted i On u.UVID = i.UVID Insert Into @UVDWithUVH(DocID) Select Distinct u.DocID From UVD As u With (Nolock) Join UVH As uh With (Nolock) on u.UVID = uh.UVID Where Not Exists (Select 1 From inserted As i Where i.UVID = u.UVID) And uh.IsLock = 1 Update r Set EDR_IsLock = @il From RED As r Join ( Select a.DocID From @UVD As a Left Outer Join @UVDWithUVH As b On a.DocID = b.DocID Where b.DocID Is Null ) As t On r.docid = t.DocID 

Dans cette solution, je suggère d'utiliser la variable @Table, qui sera située dans le Ram au lieu du stockage physique. Et supprimez la surcharge d'interrogation distincte à l'intérieur de la requête interne lors de la jointure.

Essayez aussi cette mise à jour, et j'aimerais savoir, cela vous aide-t-il à augmenter la performance de votre triggersur.