Bonjour,
On peut effectivement placer l'activation et la désactivation des déclencheurs au sein d'une transaction explicite.
Mais comme l'a exposé aieeeuuuuu, vous allez rencontrer des problèmes d'accès.
Comme évoqué auparavant, la revue du plan de requête permettra de voir ce que l'on peut faire pour optimiser l'exécution de la requête.
Vous pouvez pour ce faire vous en remettre à SQL Sentry Plan Explorer, qui permet en plus d'anonymiser le plan de requête : vous serez donc en mesure de le partager ici.
Pourriez-vous aussi n'exécuter que le SELECT que aieeeuuuuu a repris de votre code, en le précédant de SET STATISTICS IO, TIME ON ?
Ceci nous donnera des informations sur les IOs pour chaque table participant à la requête, le temps CPU consommé, et la durée d'exécution de la requête.
Le plus dur sera de mapper le nom de ces tables à ceux obtenus par anonymisation du plan de requête avec SQL Sentry Plan Explorer.
Enfin, pour l'avoir fait un grand nombre de fois : vous pouvez stocker la valeur de la clé primaire de la table cible de la mise à jour dans une table que l'on qualifier d'utilitaire ou d'annexe.
Avec celle-ci, vous pouvez vous contenter de ne stocker que les colonnes nécéssaires au calcul / à la récupération des caractéristiques du prix.
Vous pouvez ensuite réaliser les calculs et stocker dans des colonnes additionnelles à cette table d'annexe les caractéristiques des prix à stocker dans la table cible.
Une fois tout cela réalisé, il suffit de batcher l'UPDATE, comme suggéré par aieeeuuuuu : c'est alors un UPDATE sur une équi-jointure, par exemple de 10000 lignes.
Comme la transaction est petite, on n'a pas besoin de se soucier de l'effet sur le fichier du journal de transactions, si ce n'est peut-être augmenter la fréquence des sauvegardes du fichier du journal des transactions. Par ailleurs, si l'on souhaite arrêter le travail en cours de route à cause des situations de blocage qu'il génère, le travail déjà effectué n'est pas perdu.
Le squelette de cette approche est :
Veillez bien à ce que la PK de la table d'annexe soit précisément la même que la table cible de la mise à jour.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 SET NOCOUNT ON DECLARE @i int = 0 , @dt datetime WHILE EXISTS ( SELECT * FROM dbo.maTableAnnexe ) BEGIN BEGIN TRY SELECT @dt = GETDATE() , @i += 1 BEGIN TRANSACTION ;WITH CTE AS ( SELECT TOP 10000 colonnes_PK , autresColonnes FROM dbo.maTableAnnexe ORDER BY colonnes_PK ) UPDATE dbo.maTableCible FROM dbo.maTableCible AS C INNER JOIN CTE AS T ON T.colonnes_PK = C.colonnes_PK ;WITH CTE AS ( SELECT TOP 10000 colonnes_PK , autresColonnes FROM dbo.maTableAnnexe ORDER BY colonnes_PK ) DELETE FROM dbo.maTableAnnexe FROM dbo.maTableAnnexe AS A INNER JOIN CTE AS C ON A.colonnes_PK = C.colonnes_PK COMMIT TRANSACTION PRINT 'Batch #' + CAST(@i AS varchar(10)) + ' | Duration (ms) : ' + CAST(DATEDIFF(ms, @dt, GETDATE()) AS varchar(10)) END TRY BEGIN CATCH DECLARE @err_msg nvarchar(4000) = 'Line ' + CAST(ERROR_LINE() AS varchar(10)) + ' - Error Number : ' + CAST(ERROR_NUMBER() AS varchar(10)) + ' - ' + ERROR_MESSAGE() , @err_svt int = ERROR_SEVERITY() , @err_stt int = ERROR_STATE() IF XACT_STATE() <> 0 BEGIN ROLLBACK TRANSACTION; END RAISERROR(@err_msg, @err_svt, @err_stt); RETURN; END CATCH END
Si vous devez arrêter le lot en cours de route, veillez bien à exécuter un ROLLBACK TRANSACTION, de façon à libérer les verrous acquis.
@++
Partager